You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何监听UserDefaults所有键路径?新增设置无需额外代码

监听UserDefaults所有键值变化的解决方案

UserDefaults的KVO机制**不支持使用通配符***来监听所有键路径的变化,你提到的forKeyPath: "*"写法是无效的。要实现“监听所有设置项变化、新增设置无需额外代码”的需求,可以用以下两种可靠方案:

方案一:监听系统自带的通知

系统提供了UserDefaults.didChangeNotification通知,每当UserDefaults中任意键值发生变化时都会触发该通知,且能获取到具体变化的键列表。

示例代码

// 在初始化代码中添加通知观察者
NotificationCenter.default.addObserver(
    self,
    selector: #selector(handleUserDefaultsChange(_:)),
    name: UserDefaults.didChangeNotification,
    object: UserDefaults.standard
)

// 处理通知的方法
@objc private func handleUserDefaultsChange(_ notification: Notification) {
    // 获取所有变化的键
    guard let changedKeys = notification.userInfo?[UserDefaults.changedKeysKey] as? [String] else {
        return
    }
    
    // 对每个变化的键执行统一逻辑
    for key in changedKeys {
        let newValue = UserDefaults.standard.value(forKey: key)
        // 这里替换成你的实际处理代码
        print("设置项 \(key) 已更新为: \(newValue ?? "nil")")
    }
}

// 记得在对象销毁时移除观察者
deinit {
    NotificationCenter.default.removeObserver(self)
}

优缺点

  • 优点:无需自定义子类,系统原生支持,实现简单;新增设置项自动被监听,无需额外修改代码。
  • 缺点:通知触发存在轻微延迟;如果多个键值同时修改,只会触发一次通知。

方案二:自定义UserDefaults子类

通过重写UserDefaults的设置方法,在每次修改值时主动触发自定义通知或回调,这种方式更灵活,能精准控制触发时机。

示例代码

class TrackedUserDefaults: UserDefaults {
    // 定义自定义通知名称
    static let didChangeNotification = Notification.Name("TrackedUserDefaultsDidChange")
    
    // 重写基础set方法
    override func set(_ value: Any?, forKey defaultName: String) {
        super.set(value, forKey: defaultName)
        postChangeNotification(key: defaultName, value: value)
    }
    
    // 重写其他类型的set方法,确保覆盖所有修改场景
    override func set(_ value: Int, forKey defaultName: String) {
        super.set(value, forKey: defaultName)
        postChangeNotification(key: defaultName, value: value)
    }
    
    override func set(_ value: Bool, forKey defaultName: String) {
        super.set(value, forKey: defaultName)
        postChangeNotification(key: defaultName, value: value)
    }
    
    // 统一发送通知的方法
    private func postChangeNotification(key: String, value: Any?) {
        NotificationCenter.default.post(
            name: Self.didChangeNotification,
            object: self,
            userInfo: ["key": key, "value": value]
        )
    }
}

// 使用方式
let trackedDefaults = TrackedUserDefaults.standard

// 添加观察者
NotificationCenter.default.addObserver(
    self,
    selector: #selector(handleTrackedDefaultsChange(_:)),
    name: TrackedUserDefaults.didChangeNotification,
    object: trackedDefaults
)

// 处理通知
@objc private func handleTrackedDefaultsChange(_ notification: Notification) {
    guard let key = notification.userInfo?["key"] as? String,
          let value = notification.userInfo?["value"] else {
        return
    }
    // 你的统一处理逻辑
    print("设置项 \(key) 已更新为: \(value)")
}

// 销毁时移除观察者
deinit {
    NotificationCenter.default.removeObserver(self)
}

优缺点

  • 优点:触发时机精准,可自定义通知携带的信息;能完全控制所有修改操作的监听。
  • 缺点:需要确保所有设置操作都通过自定义子类执行,否则无法监听;需要重写多个set方法覆盖不同数据类型。

内容的提问来源于stack exchange,提问作者Darren Oakey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 22:01:09