2013-12-15 1 views
21

Quindi conosco il motivo di questo errore, ma non sono proprio sicuro di come aggirarlo.'NSInternalInconsistencyException', motivo: 'Esegui solo sul thread principale!' error

Ho un TextField che non voglio essere modificabile, ma con lo scorrimento abilitato all'interno di una vista.

Ecco come ho creato quella vista:

- (void)tableView:(UITableView *) tableView 
didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ 
    NSDictionary *component = self.resultsTuples[indexPath.row]; 
    NSString* serverUrl = @"http://staging.toovia.com"; 
    NSString* pageLink = component[@"$element"][@"ContactCard"][@"PageLink"]; 
    NSString* recUrl =[NSString stringWithFormat:@"%@%@&format=json&fields=summary&fields=session_info", serverUrl,pageLink]; 

    [AJAXUtils getAsyncJsonWithUrl:(NSURL *)[NSURL URLWithString:recUrl] callback:^(NSDictionary *returnjson){ 
     if (returnjson != nil){ 
      NSLog(@"RETURN JSON : %@", returnjson); 
      NSString *userPageLink = returnjson[@"Node"][@"SessionInfo"][@"PostingAs"][@"Key"]; 
      self.detailController.userPageLink = userPageLink; 
      self.detailController.nodePage = returnjson[@"Node"][@"Key"]; 
      NSString *selectedCard = component[@"$element"][@"Title"]; 
     // [self.detailController setDescription:component[@"element"][@"ContactCard"][@"Description"]]; 
      [self.detailController setPageTitle:selectedCard]; 
      NSString* photoUrl = component[@"$element"][@"ContactCard"][@"Cover"][@"Medium"][@"Link"]; 
      [self.detailController setRestaurantImage:[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:photoUrl]]]]; 



      self.detailController.title = selectedCard; 

      NSString* rating = component[@"$element"][@"Summary"][@"AverageRating"]; 
      self.detailController.rating =(NSInteger)rating; 
      [self.navigationController pushViewController:self.detailController animated:YES]; 
     } 
    }]; 

Questo è il codice viewWillAppear per la vista:

-(void)viewWillAppear:(BOOL)animated{ 
    [super viewWillAppear: animated]; 
    self.rateView.notSelectedStar =[UIImage imageNamed:@"star-off.png"]; 
    self.rateView.fullSelectedStar = [UIImage imageNamed:@"star-on.png"]; 
    self.rateView.rating = self.rating; 
    self.rateView.editable = YES; 
    self.rateView.maxRating = 5; 
    self.rateView.delegate = self; 
    _pageTitleLabel.text = _pageTitle; 
    _pageScoreLabel.text = _pageScore; 
    _trendingImageView.image = [UIImage imageNamed:@"trending.png"]; 
    _restaurantImageView.image = _restaurantImage; 

} 

L'errore completo è -

2013-12-16 01:22:50.362 ReviewApp[7332:441f] *** Assertion failure in void _UIPerformResizeOfTextViewForTextContainer(NSLayoutManager *, UIView<NSTextContainerView> *, NSTextContainer *, NSUInteger)(), /SourceCache/UIFoundation_Sim/UIFoundation-258.1/UIFoundation/TextSystem/NSLayoutManager_Private.m:1510 
2013-12-16 01:22:50.365 ReviewApp[7332:441f] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Only run on the main thread!' 

Così ho Immagino che accada perché il ridimensionamento del campo di testo (quando il contenuto è impostato) deve avvenire sul filo principale. Come faccio a forzare questo accada/sopprimere questo errore? Non ho il controllo del ridimensionamento del campo di testo, vero?

Grazie

+1

Presumibilmente nel blocco callback per 'getAsyncJsonWithUrl'? – Wain

+0

Non ho familiarità con 'getAsyncJsonWithUrl' ma, con il nome, immagino sia su un thread in background. Cerca documenti sull'esecuzione di un selettore sul thread principale o sull'invio di un blocco alla coda principale. –

risposta

49

Suppongo che la richiamata da AJAXUtils avvenga su un thread in background. Non so se questo è il tuo codice o no, ma dovresti fare tutte le operazioni dell'interfaccia utente (come l'impostazione del testo in un'etichetta, l'impostazione di un'immagine in una vista immagine, la spinta di un controller della vista) sul thread principale.

dispatch_sync(dispatch_get_main_queue(), ^{ 
    /* Do UI work here */ 
}); 
+0

ah forte - perché ho forzato questo? – praks5432

+0

@ praks5432 perché le operazioni dell'interfaccia utente non sono thread-safe (è più performante se non si deve mai bloccare/sbloccare). Costringervi ad usare un singolo thread porta via il bisogno di quelle cose. –

+0

oh, quindi è per costringerli ad essere sequenziali. Fantastico - a parte questa risposta ha funzionato, in attesa di accettare. – praks5432

5

È sempre necessario eseguire il codice UI sul thread principale. Non lo sei, quindi l'errore. Prova questo:

[AJAXUtils getAsyncJsonWithUrl:(NSURL *)[NSURL URLWithString:recUrl] callback:^(NSDictionary *returnjson){ 
    if (returnjson != nil){ 
     NSLog(@"RETURN JSON : %@", returnjson); 
     NSString *userPageLink = returnjson[@"Node"][@"SessionInfo"][@"PostingAs"][@"Key"]; 
     self.detailController.userPageLink = userPageLink; 
     self.detailController.nodePage = returnjson[@"Node"][@"Key"]; 
     NSString *selectedCard = component[@"$element"][@"Title"]; 
    // [self.detailController setDescription:component[@"element"][@"ContactCard"][@"Description"]]; 
     [self.detailController setPageTitle:selectedCard]; 
     NSString* photoUrl = component[@"$element"][@"ContactCard"][@"Cover"][@"Medium"][@"Link"]; 
     [self.detailController setRestaurantImage:[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:photoUrl]]]]; 

     self.detailController.title = selectedCard; 

     NSString* rating = component[@"$element"][@"Summary"][@"AverageRating"]; 
     self.detailController.rating =(NSInteger)rating; 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      [self.navigationController pushViewController:self.detailController animated:YES]; 
     }); 
    } 
}]; 

Ciò garantisce che la visualizzazione del controller di visualizzazione sia sulla filettatura principale. Potrebbe essere necessario aggiungere un altro po 'del codice all'interno della chiamata a dispatch_async.

2

versione Swift

dispatch_async(dispatch_get_main_queue()){ 
     /* Do UI work here */ 
} 
11

Swift 3.0 versione

DispatchQueue.main.async(execute: { 
    /* Do UI work here */ 
}) 
1

Inoltre, non è un buon modo di fare le cose in didSelectRow. Dovresti avere un livello di rete, separare il codice di rete dai controller di visualizzazione, altrimenti ti ritroverai con un enorme controller di visualizzazione, il codice non sarà testabile.