【问题标题】:'NSInternalInconsistencyException', reason: 'Only run on the main thread!' error'NSInternalInconsistencyException',原因:'只在主线程上运行!'错误
【发布时间】:2013-12-15 17:27:05
【问题描述】:

所以我知道这个错误的原因,但我不确定如何解决它。

我有一个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!'

所以我猜这是因为文本字段的大小调整(设置内容时)必须在主线程上发生。我如何强制这种情况发生/抑制这个错误?我无法控制文本字段的大小调整吗?

谢谢

【问题讨论】:

  • 大概在getAsyncJsonWithUrl的回调块中?
  • 我不熟悉getAsyncJsonWithUrl,但从名字上看,我猜它在后台线程上。查找有关在主线程上执行选择器或将块分派到主队列的文档。

标签: ios iphone objective-c multithreading cocoa-touch


【解决方案1】:

我猜来自AJAXUtils 的回调发生在后台线程上。我不知道这是否是您的代码,但您应该在主线程上执行所有 UI 操作(例如在标签中设置文本、在图像视图中设置图像、推送视图控制器)。

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

【讨论】:

  • @praks5432 因为 UI 操作不是线程安全的(如果您永远不必锁定/解锁,它的性能会更高)。强迫你使用单线程消除了对这些东西的需求。
  • 哦,所以这是强制它们顺序的。酷 - 顺便说一句,这个答案有效,等待接受。
  • 太棒了!谢谢。
【解决方案2】:

Swift 3.0 版本

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

【讨论】:

    【解决方案3】:

    您必须始终在主线程上执行 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 的调用中添加更多代码。

    【讨论】:

      【解决方案4】:

      斯威夫特版本

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

      【讨论】:

        【解决方案5】:

        另外,在 didSelectRow 中这不是一种很好的处理方式。您应该有一个网络层,将网络代码与视图控制器分开,否则您最终会得到巨大的视图控制器,代码将无法测试。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-01-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多