前言
前段時間看app的線上奔潰總是出現(xiàn)意義不明的崩潰問題,而且崩潰棧出現(xiàn)在閉包的回調(diào)里,并且bugly上提示說是有可能在swift解包的時候出現(xiàn)問題,也就是對nil使用了!。這就完全誤導(dǎo)了我,把我對問題的理解定義為數(shù)據(jù)保護的不夠到位。結(jié)果就是在多次發(fā)版后這個問題還未得到解決,所以我絕對對這個問題一探究竟。
出現(xiàn)問題的原因
其實出現(xiàn)這個問題的原因很簡單,那就是group的enter和leave沒有成對出現(xiàn)。比如說我們會在閉包的回調(diào)里去leave,但是閉包有可能返回多次,一旦多l(xiāng)eave了,那么就會出現(xiàn)EXC_BAD_INSTRUCTION這個問題。
舉個例子
我們聲明如下兩個方法,可以看出來work2回調(diào)了兩次
func work1(closure: () -> Void) {
sleep(1)
closure()
}
func work2(closure: () -> Void) {
closure()
sleep(2)
closure()
}
接著我們使用它們
override func viewDidLoad() {
super.viewDidLoad()
let group = DispatchGroup()
let queue = DispatchQueue(label: "test", qos: .background, attributes: .concurrent, autoreleaseFrequency: .inherit, target: nil)
group.enter()
queue.async {
self.work1 {
group.leave()
}
}
group.enter()
queue.async {
self.work2 {
group.leave()
}
}
group.notify(queue: queue) {
print("同步完成")
}
}
這里可以看出來在work2的閉包的leave就會出現(xiàn)這個問題。
解決方法
其實這種問題完全使我們編寫代碼的過程中不夠細心導(dǎo)致的,通過完善的測試用例完全可以避免問題發(fā)生,但是我們還是需要記住一句話DispatchGroup的enter和leave必須成對出現(xiàn)!!!