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

UserDefaults.setValue() 是否有官方文档?其KVC适配逻辑是什么?

关于UserDefaults.setValue()的疑问

我偶尔会看到有人使用UserDefaults.setValue()方法,以下是找到的可用示例代码:

@propertyWrapper struct AppSetting<Value> {
    let key: String
    let defaultValue: Value
    var container: UserDefaults = .standard

    var wrappedValue: Value {
        get { container.value(forKey: key) as? Value ?? defaultValue}
        set { container.setValue(newValue, forKey: key) }
    }
}

从Apple文档中我了解到,setValue()是NSObject用于KVC(键值编码)的API,UserDefaults类继承自NSObject。但我不清楚在UserDefaults实例上调用该方法的具体作用,从示例推测UserDefaults可能重写了此方法,否则按常规理解它只会设置UserDefaults对象的属性,这毫无意义。

我想知道:这种用法是如何被发现的?是否有官方文档说明?

补充说明1

我了解KVO(键值观察)的概念,我的困惑点在于KVC与UserDefaults的关联。我认为KVC中的“键”是对象的属性名,而UserDefaults中的“键”是键值存储的键,二者意义完全不同。为何用于KVC的API能更新UserDefaults的键值对?难道UserDefaults会为每个存储键创建对应的属性?这似乎是未公开的实现细节。

补充说明2

正如@rob-mayoff和@HangarRash指出的,setValue()是KVC而非KVO的API,但我的核心疑问仍然成立。


解答

  1. UserDefaults对KVC方法的重写
    UserDefaults确实重写了NSObject的KVC相关方法(包括setValue(_:forKey:)和value(forKey:)),这是公开的设计行为,并非未公开细节。Apple这么做是为了让开发者可以通过KVC语法来访问和修改UserDefaults中的存储键值对,本质上是将KVC的“键”映射到了UserDefaults的存储键,而非对象自身的属性。

  2. 官方文档的说明
    虽然Apple没有在UserDefaults的主文档中单独突出setValue(_:forKey:),但在NSObject的KVC文档中明确提到,子类可以重写KVC方法来自定义键的解析逻辑。同时,UserDefaults官方推荐的set(_:forKey:)方法,和setValue(_:forKey:)的核心行为一致——唯一区别是setValue(_:forKey:)接受Any?类型,传入nil时会移除对应存储键;而set(_:forKey:)要求非可选类型,若要移除键需使用removeObject(forKey:)。

  3. 这种用法的发现途径

  • 早期Objective-C开发中,KVC是主流语法之一,开发者自然会尝试用KVC方法操作UserDefaults,验证可行后逐渐流传;
  • Apple在旧版技术文档或示例代码中曾使用过该写法;
  • 开发者通过查看系统框架头文件或开源代码,确认了UserDefaults对KVC方法的重写实现。
  1. 关于存储键与属性的误解
    UserDefaults并不会为每个存储键创建对应的对象属性,它只是在重写KVC方法时,将传入的“键”直接映射到内部的键值存储字典。调用setValue(_:forKey:)时,不会修改UserDefaults对象自身的属性,而是把值存入持久化存储,这完全是UserDefaults对KVC接口的自定义适配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 08:20:48