2013-12-15 2 views
21

Also ich kenne den Grund für diesen Fehler, aber ich bin nicht wirklich sicher, wie ich es umgehen soll.'NSInternalInconsistencyException', Grund: 'Nur auf dem Hauptthread ausführen!' Fehler

Ich habe eine TextField, die ich nicht bearbeiten möchte, aber mit Scrollen in einer Ansicht aktiviert.

Dies ist, wie ich festgelegt, dass die Ansicht auf:

- (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]; 
     } 
    }]; 

Dies ist der viewWillAppear Code für die Ansicht:

-(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; 

} 

Der vollständige Fehler ist -

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!' 

I So Ich vermute, es passiert, weil die Größenänderung des Textfelds (wenn der Inhalt eingestellt ist) auf der Haupt-Bedroung. Wie kann ich dies erzwingen/diesen Fehler unterdrücken? Ich habe nicht die Kontrolle über das Textfeld Größenanpassung bin ich?

Dank

+1

Vermutlich im Callback-Block für 'getAsyncJsonWithUrl'? – Wain

+0

Ich bin nicht vertraut mit 'getAsyncJsonWithUrl', aber mit dem Namen würde ich vermuten, dass es auf einem Hintergrundthread ist. Suchen Sie nach Dokumenten zum Ausführen eines Selektors im Hauptthread oder zum Senden eines Blocks an die Hauptwarteschlange. –

Antwort

49

Ich vermute, dass der Rückruf von AJAXUtils auf einem Hintergrundthread passiert. Ich weiß nicht, ob das dein Code ist oder nicht, aber du solltest alle UI-Operationen (wie das Setzen von Text in einem Label, das Setzen eines Bildes in einer Bildansicht, das Drücken eines View-Controllers) auf dem Haupt-Thread ausführen.

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

ah cool - warum hat ios das erzwungen? – praks5432

+0

@ praks5432, weil UI-Operationen nicht Thread-sicher sind (es ist leistungsfähiger, wenn Sie nie sperren/entsperren müssen). Wenn Sie gezwungen werden, einen einzelnen Thread zu verwenden, brauchen Sie diese Dinge nicht mehr. –

+0

oh, so ist es, um sie sequenziell zu zwingen. Cool - diese Antwort funktionierte und wartete darauf, akzeptiert zu werden. – praks5432

5

Sie müssen UI-Code immer auf dem Hauptthread ausführen. Du bist nicht, daher der Fehler. Versuchen Sie folgendes:

[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]; 
     }); 
    } 
}]; 

Dies stellt sicher, dass die Anzeige des View-Controllers auf dem Haupt-Thread ist. Möglicherweise müssen Sie etwas mehr Code in den Aufruf von dispatch_async einfügen.

2

Swift Version

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

Swift 3.0 Version

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

Außerdem ist es nicht eine sehr gute Art, die Dinge in didSelectRow. Sie sollten eine Netzwerkschicht haben, trennen Sie den Netzwerk-Code von View-Controllern, sonst werden Sie mit riesigen View-Controller, Code wird nicht testbar sein.