web-dev-qa-db-fra.com

'NSInternalInconsistencyException', raison: 'Exécuter uniquement sur le thread principal!' Erreur

Je connais donc la raison de cette erreur, mais je ne sais pas vraiment comment la contourner.

J'ai un TextField que je ne veux pas être modifiable, mais avec le défilement activé dans une vue.

Voici comment j'ai configuré cette vue:

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

Voici le code viewWillAppear pour la vue:

-(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'erreur complète est -

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

Je suppose donc que cela se produit parce que le redimensionnement du champ de texte (lorsque le contenu est défini) doit se produire sur le thread principal. Comment puis-je forcer cela à se produire/supprimer cette erreur? Je ne contrôle pas le redimensionnement du champ de texte, n'est-ce pas?

Merci

23
praks5432

Je suppose que le rappel de AJAXUtils se produit sur un thread d'arrière-plan. Je ne sais pas si c'est votre code ou non, mais vous devriez faire toutes les opérations d'interface utilisateur (comme définir du texte dans une étiquette, définir une image dans une vue d'image, pousser un contrôleur de vue) sur le thread principal.

dispatch_sync(dispatch_get_main_queue(), ^{
    /* Do UI work here */
});
52
David Rönnqvist

Version Swift 3.0

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

Vous devez toujours exécuter du code d'interface utilisateur sur le thread principal. Vous ne l'êtes pas, d'où l'erreur. Essaye ça:

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

Cela garantit que l'affichage du contrôleur de vue est sur le thread principal. Vous devrez peut-être mettre un peu plus de code dans l'appel à dispatch_async.

6
rmaddy

Version Swift

dispatch_async(dispatch_get_main_queue()){
      /* Do UI work here */
}
2
Manuel Escrig

De plus, ce n'est pas une très bonne façon de faire les choses dans didSelectRow. Vous devriez avoir une couche réseau, séparer le code réseau des contrôleurs de vue, sinon vous vous retrouverez avec un contrôleur de vue énorme, le code ne sera pas testable.

1
Buhaescu Vlad