这段代码
DispatchQueue(label: "Timer").async {[weak self] in
guard let self = self else{return}
self.runLoop = RunLoop.current
RunLoop.current.add(timer, forMode: .defaultRunLoopMode)
RunLoop.current.run()
print("end")
print("\(self.description)")
}
即使在block中声明self为weak,但只要在RunLoop.current.run()前做guard let self = self else{return},但RunLoop.current.run()后面代码再度调用self将会强持有self
产生这个结果的三个条件:
block中声明[weak self];
RunLoop.current.run()前做guard let self = self else{return};
RunLoop.current.run()后面再度调用self
下面是测试结果
class TestsController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.view.backgroundColor = .white
// runLoopTest()
// runLoopTest2()
runLoopTest3()
}
var timer:Timer?
var runLoop:RunLoop?
func runLoopTest() {
var count = 0
let timer = Timer(timeInterval: 2, repeats: true) { (timer) in
print("\(count)")
count += 1
}
self.timer = timer
DispatchQueue(label: "Timer").async {[weak self] in
//如果RunLoop.current.run()之后还有调用self,将会强持有self
guard let self = self else{return}
self.runLoop = RunLoop.current
RunLoop.current.add(timer, forMode: .defaultRunLoopMode)
RunLoop.current.run()
print("end")
print("\(self.description)")
}
}
/*结果:
0
1
2
......
即使pop后依然会继续timer
*/
//正常运行
func runLoopTest2() {
var count = 0
let timer = Timer(timeInterval: 2, repeats: true) { (timer) in
print("\(count)")
count += 1
}
self.timer = timer
// DispatchQueue(label: "Timer").async {[unowned self] in//使用无主引用会崩溃,因为self已为nil,再调用会崩
DispatchQueue(label: "Timer").async {[weak self] in
self?.runLoop = RunLoop.current
RunLoop.current.add(timer, forMode: .defaultRunLoopMode)
RunLoop.current.run()
print("end")
print("\(self?.description ?? "nil")")
}
}
/*结果:
0
1
2
deinit
end
nil
*/
//正常运行
func runLoopTest3() {
var count = 0
let timer = Timer(timeInterval: 2, repeats: true) { (timer) in
print("\(count)")
count += 1
}
self.timer = timer
// DispatchQueue(label: "Timer").async {[unowned self] in//使用无主引用会崩溃
DispatchQueue(label: "Timer").async {[weak self] in
self?.runLoop = RunLoop.current
RunLoop.current.add(timer, forMode: .defaultRunLoopMode)
RunLoop.current.run()
print("end")
//写在RunLoop.current.run()之后就不会强持有,不过self已是nil,不会有打印
guard let self = self else{return}
print("\(self.description)")
}
}
/*结果:
0
1
deinit
end
*/
deinit {
print("deinit")
self.timer?.invalidate()
if let rl = self.runLoop?.getCFRunLoop() {
CFRunLoopStop(rl)
}
}
}