为什么从前台调用某些东西会崩溃,而从后台调用它却不会?
Why would calling something from the foreground crash, when calling it from the background does not?
好的,(又)对 ObjectiveC 比较陌生,来自 Swift 背景。在我们的代码库中,我们有这行代码...
return _queryURL && ![[UIApplication sharedApplication] canOpenURL:_queryURL];
虽然它可以工作,但在调试时,Xcode 会发出警告,指出 canOpenURL
必须从前台线程执行。
'Simple enough' 我想...'我会在前台线程上同步调用它!'然后我更新代码如下...
__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
在主线程上调用某些东西时 已经 在主线程上。
我认为,根据您收到的错误和警告,您有时会在后台调用它,有时会在 main 上调用它。因此,您需要使用例如
进行检查
NSThread.isMainThread
或类似的在你打电话之前,然后根据那个继续,也许
if ( NSThread.isMainThread )
{
// my call
}
else
{
dispatch_sync( dispatch_get_main_queue (), ^ {
// my call
} );
}
但是,如果确实是有时从主调用有时从后台调用的情况,你还需要验证其背后的逻辑是否合理。
为了补充正确答案,我 运行 经常参与其中(通常在 属性 观察者中),我为此创建了一个函数:
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;
好的,(又)对 ObjectiveC 比较陌生,来自 Swift 背景。在我们的代码库中,我们有这行代码...
return _queryURL && ![[UIApplication sharedApplication] canOpenURL:_queryURL];
虽然它可以工作,但在调试时,Xcode 会发出警告,指出 canOpenURL
必须从前台线程执行。
'Simple enough' 我想...'我会在前台线程上同步调用它!'然后我更新代码如下...
__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
在主线程上调用某些东西时 已经 在主线程上。
我认为,根据您收到的错误和警告,您有时会在后台调用它,有时会在 main 上调用它。因此,您需要使用例如
进行检查NSThread.isMainThread
或类似的在你打电话之前,然后根据那个继续,也许
if ( NSThread.isMainThread )
{
// my call
}
else
{
dispatch_sync( dispatch_get_main_queue (), ^ {
// my call
} );
}
但是,如果确实是有时从主调用有时从后台调用的情况,你还需要验证其背后的逻辑是否合理。
为了补充正确答案,我 运行 经常参与其中(通常在 属性 观察者中),我为此创建了一个函数:
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;