为什么从前台调用东西会崩溃,而从后台调用却不会



好的,对ObjectiveC来说还是比较新的,来自Swift背景。在我们的代码库中,我们有这行代码。。。

return _queryURL && ![[UIApplication sharedApplication] canOpenURL:_queryURL];

当它工作时,在调试时,Xcode会发出警告,说明canOpenURL必须从前台线程执行。

"很简单"我想我只会在前台线程上同步调用它!"我更新代码如下。。。

__block BOOL result = NO;

dispatch_sync(dispatch_get_main_queue(), ^{
result = _queryURL && ![[UIApplication sharedApplication] canOpenURL:_queryURL];
});
return result;

但现在,当执行调用canOpenURL的行时,我得到了。。。

Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)

啊?!为什么将它推送到主线程会导致EXC_BAD_INSTRUCTION崩溃?这是在转移注意力吗?

更重要的是,你如何解决这个问题?

我看到,当您在主线程上sync调用某个东西时,会发生错误指令错误。

我认为,根据你得到的错误和警告,你有时在后台调用这个,有时在主屏幕上调用。因此,您需要使用例如进行检查

NSThread.isMainThread

或者在你打电话之前类似的事情,然后根据这个过程,也许

if ( NSThread.isMainThread )
{
// my call
}
else
{
dispatch_sync( dispatch_get_main_queue (), ^ {
// my call
} );
}

然而,如果您有时从main调用,有时从后台调用,那么您还需要验证其背后的逻辑是否合理。

为了增加正确答案,我经常遇到这种情况(通常在属性观测器中(,为此我创建了一个函数:

void ExecuteOnMain( dispatch_block_t block )
{
// Shorthand for synchronously executing a block on the main thread before returning.
// Unlike dispatch_sync(), this won't deadlock if executed on the main thread.
if (NSThread.isMainThread)
block(); // main thread: execute the block immediately
else
dispatch_sync(dispatch_get_main_queue(),block); // not the main thread, queue the block
}

然后,你所要写的就是

__block BOOL result = NO;

ExecuteOnMain(), ^{
result = _queryURL && ![[UIApplication sharedApplication] canOpenURL:_queryURL];
});
return result;

相关内容

  • 没有找到相关文章

最新更新