swift3:调度队列挂起和恢复崩溃应用程序:线程1 exc_bad_指令(代码=exc_i386_invop子代码=0x0)
我正在使用tvos创建琐事视图,其中4个UILabel作为子视图添加,每个UILabel在登录后在自定义队列上调度 用于对队列进行调度的函数为:swift3:调度队列挂起和恢复崩溃应用程序:线程1 exc_bad_指令(代码=exc_i386_invop子代码=0x0),swift3,queue,xcode8,tvos,dispatch,Swift3,Queue,Xcode8,Tvos,Dispatch,我正在使用tvos创建琐事视图,其中4个UILabel作为子视图添加,每个UILabel在登录后在自定义队列上调度 用于对队列进行调度的函数为: func delayWithSeconds(_ seconds: Double, completion: @escaping () -> ()) { self.TriviaDispatchQueue?.asyncAfter(deadline: .now() + seconds, qos: .default, flags: DispatchWo
func delayWithSeconds(_ seconds: Double, completion: @escaping () -> ()) {
self.TriviaDispatchQueue?.asyncAfter(deadline: .now() + seconds, qos: .default, flags: DispatchWorkItemFlags.detached, execute: {
DispatchQueue.main.sync {
completion()
}
})
}
我的调度代码是:
func showTrivia() {
self.TriviaDispatchQueue = DispatchQueue(label: "TriviaQueue")
self.delayWithSeconds(5, completion: {
self.fadeIn(forView: self.Answer0Lbl)
self.delayWithSeconds(2, completion: {
self.fadeIn(forView: self.Answer1Lbl)
self.delayWithSeconds(2, completion: {
self.fadeIn(forView: self.Answer2Lbl)
self.delayWithSeconds(2, completion: {
self.fadeIn(forView: self.Answer3Lbl)
})
})
})
})
}
所以,当用户从顶部菜单中的琐事视图移动到电视中的其他视图时,队列将暂停以停止琐事
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
onMainThread {
self.TriviaClass.TriviaDispatchQueue?.suspend()
}
}
之后,当用户返回到琐事视图时,队列将恢复:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
onMainThread {
self.TriviaClass.TriviaDispatchQueue?.resume()
}
}
第一次登录时一切正常,但在注销和再次重新登录后,应用程序崩溃:线程1 exc\u bad\u指令(代码=exc\u i386\u invop子代码=0x0)
琐事类与变量共享
var TriviaDispatchQueue: DispatchQueue?
所以我来这里的派对已经很晚了,但我可以确切地告诉你问题是什么: 调度源(此处为队列)在处于挂起状态时被解除分配。这是不允许的。(引用计数决定不再需要
TriviaClass
,但首先解除分配调度队列
)
我找不到该文档的链接,但GCD的一位工程师在这里解释道:
(我想你需要一个苹果开发者帐户来观看这些视频,但还不确定……)
解决方案:
我建议不要暂停任何
发送源代码。曾经(可能在单元测试中,但在生产代码中,您只需在代码上添加几乎不可能调试的危险定时炸弹。)如果仍然需要调度块,请在调度块中添加一个检查,或者依赖弱指针不执行您先前调度但不想再运行的代码。TriviaClass是否由您在上面粘贴代码的视图控制器所有?如果是这样,问题可能是TriviaClass在TriviaDispatchQueue挂起时被释放
根据文档,这将导致未定义的行为
重要的
释放当前挂起的对象是程序员的错误,因为挂起意味着还有工作要做。因此,在处理对象之前,始终平衡对该方法的调用和对resume()的相应调用。在分派对象处于挂起状态时释放对该对象的最后一个引用的行为未定义