好的,对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;