GCD定时器DispatchSourceTimer崩溃问题
// // SecondaryViewController.swift // 0401 // // Created by kqc on 2025/7/30. // /* * 使用DispatchSourceTimer注意点 * 1: suspend状态不能调用cancel方法会崩溃 * 2: 重复调用resume或者suspend方法崩溃,必须成对出现 * 3: 销毁时如果 resume() -> cancel() -> time = nil 会在特定机型崩溃偶发频率很高 如iPhone13,iPhone16等 * 针对3的修改,在setCancelHandler中执行对应的销毁操作 */ import UIKit class SecondaryViewController: UIViewController { var timer: DispatchSourceTimer? var count = 0 override func viewDidLoad() { super.viewDidLoad() title = "测试DispatchTime" view.backgroundColor = .white addNoti() createTimer() } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) timer?.suspend() } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) timer?.resume() } func createTimer() { timer = DispatchSource.makeTimerSource() timer?.schedule(deadline: .now(), repeating: .seconds(2), leeway: .milliseconds(100)) timer?.setEventHandler(handler: DispatchWorkItem(block: { print("测试数据...") })) // To safely close a file descriptor or destroy a Mach port, a cancellation handler is required for that descriptor or port. timer?.setCancelHandler(handler: DispatchWorkItem(block: {[weak self] in self?.timer = nil })) } func stopTimer() { guard let timer = timer else { return } timer.suspend() } func recoverTimer() { guard let timer = timer else { return } timer.resume() } func closeTimer() { timer?.resume() timer?.cancel() // self.timer = nil } func delayAction() { DispatchQueue.main.asyncAfter(deadline: .now() + 1){ self.count += 1 print(self.count) } } deinit { closeTimer() removeNoti() debugPrint("销毁") } } extension SecondaryViewController { func addNoti() { NotificationCenter.default.addObserver(self, selector: #selector(becomeActiveStatu), name: UIApplication.willEnterForegroundNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(resignActiveStatu), name: UIApplication.willResignActiveNotification, object: nil) } func removeNoti() { NotificationCenter.default.removeObserver(self) } @objc func becomeActiveStatu() { recoverTimer() } @objc func resignActiveStatu() { stopTimer() } }