【问题标题】:Why is any code executed before this has finished?为什么在这完成之前执行任何代码?
【发布时间】:2014-04-25 12:34:26
【问题描述】:

假设我有这样的代码:

[ApiConnection getServerTimeWithBlock:^(BOOL gotTimeResponse){

    if(gotTimeResponse)
    {
        //we're online, got the response from time endpoint
        [ApiConnection registerNewCustomerWithBlock:^(NSString* val){
            if(val)
            {
                NSLog(@"val: %@",val);
            }
            else
            {
                NSLog(@"no val");
            }
        }];
    }
    else
    {
        //we're offline
    }
}];

NSLog(@"TEST");

为什么在整个第一个块执行完成之前执行最后一个 NSLog?

【问题讨论】:

  • 看起来阅读有关块和异步编码的一般知识会对您有所帮助 - 这种结构非常有用
  • @SomaMan 绝对是的,这就是我正在做的。我的错误似乎是我认为该方法只有在完成处理程序执行后才会返回。

标签: objective-c asynchronous objective-c-blocks


【解决方案1】:

因为getServerTimeWithBlock: 方法是异步的,所以它立即返回并在后台线程上运行。当该线程完成时调用完成块。

因此,该方法在您的日志之前运行,但完成块(通常)不会(如果出现错误或类似情况可能会这样)。

【讨论】:

    【解决方案2】:

    大概getServerTimeWithBlock: 是异步执行的。提供块时,您是在告诉 APIConnection 对象在完成获取服务器时间后要做什么。这将涉及网络获取和读回数据,您不想在主线程上等待,因为这会导致您的 UI 冻结。因此,您的程序会继续执行,并且在获取完成时执行该块。

    请注意,块并不意味着正在使用异步或多线程代码(例如,请参阅 NSArray 的 enumerateWithBlock: 方法),但这里似乎很可能是这种情况。

    【讨论】:

    • 我认为我需要同步检查互联网连接,否则我不知道我应该从 API 获取数据还是使用离线存储。所以我想我会在第一个请求中使用 dispatch_sync,然后异步执行所有其他请求,你认为这是一个好方法吗?
    • 没有。我认为您应该对上面的代码进行任何调用,期望该方法立即返回,并将完成块传递给该方法。然后,当您获得数据后,无论采用何种方法,您都可以执行完成块。
    • 所以我应该保持代码原样,在 getServerTimeWithBlock 调用后为数据准备 UI,然后在方法中使用完成处理程序用数据填充 UI,无论是来自 API 还是来自离线数据库?
    猜你喜欢
    • 1970-01-01
    • 2020-05-05
    • 2011-01-16
    • 2016-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多