Dre*_*rew 1 objective-c nsoperationqueue grand-central-dispatch ios
以下代码会在 iOS 模拟器中产生崩溃。
- (void)viewDidLoad
{
[super viewDidLoad];
dispatch_async(dispatch_get_main_queue(), ^{
NSDate *sleepStart = [NSDate date];
while ([sleepStart timeIntervalSinceNow] > -300) {
}
});
}
Run Code Online (Sandbox Code Playgroud)
更新:即使在后台线程上也会出现此问题。
下面的代码也有错误:
- (void)viewDidLoad
{
[super viewDidLoad];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSDate *sleepStart = [NSDate date];
while ([sleepStart timeIntervalSinceNow] > -300) {
}
});
}
Run Code Online (Sandbox Code Playgroud)
就这样。将其粘贴到任何视图控制器中,在模拟器中运行该应用程序正好 4 分 15 秒,它就会崩溃。
这种崩溃是我以前从未见过的。是“EXC_???(11)”。奇怪的是,您可以在崩溃后按“继续”按钮,它会像平常一样继续。
为什么会崩溃?如何将长任务提交到队列而不导致此行为?
到目前为止,我尝试过以下一些方法,但还没有解开这个谜团:
更新#1
该问题仅在 LLDB 下重现,在 GDB 下不重现。
您不能在主线程上执行冗长的操作。您应该将块分派到另一个线程,然后在块结束时分派回主线程(如果需要)。
使用dispatch_async(dispatch_get_main_queue(),^{});会导致您的操作在不久的将来在主线程上执行(阻塞)。
主线程受定时器保护;如果你停止响应事件,iOS 将杀死它。这是故意的:不要在主线程上做繁重的工作!
iOS 的容忍度通常远小于四分钟,但如果您进行调试,它会变得更长。模拟器有它自己的规则。
启动时,只需几秒钟的时间。但是,您不应该在主线程上执行任何花费超过一瞬间的操作,并且只能在响应直接用户操作(例如用户点击某些内容)时执行。在主线程上工作会导致 iOS UI 响应速度变慢,变得不稳定,而不是光滑。
如果您的应用程序停止响应 OSX 上主线程上的事件,它就会陷入困境。你的应用程序停止响应 iOS 主线程上的事件,iOS 看门狗将其取出并射击它。
来自技术说明 TN2151:
异常代码 0x8badf00d 表示应用程序因发生看门狗超时而被 iOS 终止。应用程序启动、终止或响应系统事件的时间过长。造成这种情况的一个常见原因是在主线程上进行同步网络。无论线程 0 上有什么操作:都需要移至后台线程,或以不同的方式处理,这样就不会阻塞主线程。
一般来说,模式是:
- (IBAction)tappedWhatever:(id)sender {
// visually start operation
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^{
// do work here, off main thread
// (you can't update the UI here)
dispatch_async(dispatch_get_main_queue(),^{
// show progress in UI
});
// more heavy lifting
dispatch_async(dispatch_get_main_queue(),^{
// update UI to show operation complete and move to next step
});
});
};
Run Code Online (Sandbox Code Playgroud)
(我可以发誓苹果文档中有对此的更好描述,但我现在找不到。有人吗?)
| 归档时间: |
|
| 查看次数: |
1121 次 |
| 最近记录: |