从设置返回App后如何读取Settings Bundle配置?viewWillAppear未触发
解决Settings Bundle配置更新后无法触发航向更新的问题
首先,你遇到的核心问题是当App从系统设置返回时,当前ViewController的viewWillAppear方法并没有被调用——这通常发生在你的ViewController是TabBarController、NavigationController的子控制器,或者App只是从后台切换回前台(而非重新进入这个ViewController)的场景下。
下面给你两个可靠的解决方案:
方案一:监听App进入前台的通知
当用户从设置回到App时,App会触发UIApplication.willEnterForegroundNotification通知,我们可以在ViewController中监听这个通知,在通知回调里读取更新后的配置并调整locationManager的状态。
修改你的代码如下:
private let locationManager : CLLocationManager = CLLocationManager() override func viewDidLoad() { super.viewDidLoad() locationManager.requestWhenInUseAuthorization() locationManager.delegate = self // 添加通知监听 NotificationCenter.default.addObserver(self, selector: #selector(updateHeadingStatus), name: UIApplication.willEnterForegroundNotification, object: nil) // 初始化时先执行一次状态更新 updateHeadingStatus() } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) // 记得移除通知监听,避免内存泄漏 NotificationCenter.default.removeObserver(self, name: UIApplication.willEnterForegroundNotification, object: nil) } @objc private func updateHeadingStatus() { let userDefault = UserDefaults.standard // 用bool(forKey:)更安全,避免强制解包崩溃 let updateheading = userDefault.bool(forKey: "updateheading") if updateheading { locationManager.startUpdatingHeading() } else { locationManager.stopUpdatingHeading() } }
方案二:监听UserDefaults的变化
因为Settings Bundle的配置会直接同步到UserDefaults,所以我们可以监听UserDefaults.didChangeNotification通知,只要配置值发生变化,就立即更新locationManager的状态——这个方案更精准,哪怕配置是在App内部修改的,也能触发更新。
代码示例:
private let locationManager : CLLocationManager = CLLocationManager() override func viewDidLoad() { super.viewDidLoad() locationManager.requestWhenInUseAuthorization() locationManager.delegate = self // 监听UserDefaults变化通知 NotificationCenter.default.addObserver(self, selector: #selector(updateHeadingStatus), name: UserDefaults.didChangeNotification, object: nil) updateHeadingStatus() } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) NotificationCenter.default.removeObserver(self, name: UserDefaults.didChangeNotification, object: nil) } @objc private func updateHeadingStatus() { let userDefault = UserDefaults.standard let updateheading = userDefault.bool(forKey: "updateheading") updateheading ? locationManager.startUpdatingHeading() : locationManager.stopUpdatingHeading() }
额外提示
- 避免使用
object(forKey:) as! Bool这种强制解包的写法,推荐用bool(forKey:),它会在键不存在时返回默认值false,更安全。 - 如果你的App支持iOS 13+,也可以用
NotificationCenter的闭包式监听,写法更简洁,还能通过AnyCancellable自动管理监听的生命周期,无需手动移除。
内容的提问来源于stack exchange,提问作者CL So
相关产品推荐
相关产品推荐

