1

我编写了一个测试来使用块来试验 RestKit。我认为RKRequest.onDidLoadResponse需要包含一个dispatch_async()调用来获取主 UI 线程上的响应,但令我惊讶的是这会导致运行时异常,所以我把它拿出来,我可以很好地更新界面。

我有问题的代码如下:

- (IBAction)loadSeasons:(UIButton *)sender {
    [[RKClient sharedClient] get:@"/api/v1/seasons" usingBlock:^(RKRequest* req) {
        req.onDidLoadResponse = ^(RKResponse* res) {
            NSLog(@"Request Performed: %@", res.bodyAsString);
            self.textResponse.text = res.bodyAsString;
            //dispatch_async(dispatch_get_main_queue(), ^{
            //    NSLog(@"In main queue: %@", res.bodyAsString);
            //});
        };
    }];
}

如果我取消注释该dispatch_async块,我会得到异常。那么我怎么知道什么时候需要使用它,什么时候不需要呢?我是否应该测试一些东西来告诉我正在执行的代码是否在主线程上?

我是 Objective-C 的新手,对我来说还处于早期阶段,所以我为可能是新手的问题道歉。

更新:当取消注释上面的代码时,会发生以下情况:

  1. 控制台(lldb)以蓝色输出文本,未提供其他信息。
  2. objc_msgSend中断libobjc.A.dylibis shown in the editor on0x1c2009b: movl 8(%edx), %ediwith the message in green:线程 1: EXC_BAD_ACCESS (code=1, address=0x40000008)`。
4

1 回答 1

3

要回答您的问题,您可以通过调用来检查您当前的线程[NSThread isMainThread]。但是,您不需要为您的问题执行此操作,事实上,如果您已经在主线程中运行,将执行块分派到主线程是完全合法的。

崩溃是因为执行块时变量的存储方式。当第一个块完成时,变量使用的堆栈内存可以被覆盖,所以当你的异步NSLog语句在第二个块中运行时,你的变量res已经被破坏了,所以它在你的日志语句中使用时指向垃圾,触发崩溃。

为了完整性,研究__block变量声明。为了res在您的第二个调度块中引用,我相信您必须__block通过在您的第一个块中声明它来将其声明为变量以将其移动到堆:__block RKResponse* response = res;然后response在您的调度日志语句中使用。

于 2012-11-16T05:29:52.340 回答