web-dev-qa-db-ja.com

'NSInternalInconsistencyException'、理由: 'メインスレッドでのみ実行!'エラー

だから私はこのエラーの理由を知っていますが、どうやってそれを回避するのか本当にわかりません。

編集不可にしたいが、ビュー内でスクロールを有効にしたTextFieldがあります。

これは私がそのビューを設定する方法です:

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

これは、ビューのviewWillAppearコードです。

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

}

完全なエラーは-

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

したがって、テキストフィールドのサイズ変更(コンテンツが設定されている場合)がメインスレッドで行われる必要があるため、このようなことが起こっていると思います。これを強制的に発生させるにはどうすればよいですか?テキストフィールドのサイズ変更を制御できません。

ありがとう

23
praks5432

AJAXUtilsからのコールバックはバックグラウンドスレッドで発生すると思います。それがあなたのコードであるかどうかはわかりませんが、メインスレッドですべてのUI操作(ラベルでのテキストの設定、イメージビューでの画像の設定、ビューコントローラーのプッシュなど)を実行する必要があります。

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

Swift 3.0バージョン

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

常にメインスレッドでUIコードを実行する必要があります。あなたはそうではない、したがってエラー。これを試して:

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

これにより、ビューコントローラーの表示がメインスレッド上に表示されます。実際には、dispatch_asyncの呼び出し内にもう少しコードを配置する必要がある場合があります。

6
rmaddy

Swiftバージョン

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

また、didSelectRowで物事を行うにはあまり良い方法ではありません。ネットワークレイヤーが必要です。ネットワークコードをビューコントローラーから分離してください。そうしないと、ビューコントローラーが巨大になり、コードをテストできなくなります。

1
Buhaescu Vlad