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

自定义UserDefaults套件的Swift Publisher无法正常更新订阅

自定义UserDefaults套件下订阅无法触发更新的问题

当使用自定义套件的UserDefaults时,通过publisher(for:)创建的订阅只能获取初始值,后续修改值时无法触发订阅回调。但SwiftUI视图中的onReceive订阅却能正常响应值的变化。如果切换回默认的standard UserDefaults套件,所有订阅(包括直接创建的sink订阅)都能正常触发(即使存在重复调用的情况)。


自定义套件的代码示例

public extension UserDefaults {
    @objc dynamic var value1: Int {
        get { integer(forKey: "value1") }
        set { set(newValue, forKey: "value1") }
    }

    static var other: UserDefaults {
        UserDefaults(suiteName: "other-defaults")!
    }
}

struct ContentView: View {
    private let sub = UserDefaults.other.publisher(for: \.value1).sink { print("SUB", $0) }

    var body: some View {
        Button("Add") {
            UserDefaults.other.value1 += 1
            debugPrint("SET", UserDefaults.other.value1)
        }
        .onReceive(UserDefaults.other.publisher(for: \.value1)) {
            debugPrint("UI", $0)
        }
    }
}

输出结果

SUB 0
"UI" 0
"SET" 1
"UI" 1
"SET" 2
"UI" 2

可以看到,只有onReceive的订阅能响应后续值的更新,直接创建的sink订阅只输出了初始值。


默认standard套件的代码示例

struct ContentView2: View {
    private let sub = UserDefaults.standard.publisher(for: \.value1).sink { print("SUB", $0) }

    var body: some View {
        Button("Add") {
            UserDefaults.standard.value1 += 1
            debugPrint("SET", UserDefaults.standard.value1)
        }
        .onReceive(UserDefaults.standard.publisher(for: \.value1)) {
            debugPrint("UI", $0)
        }
    }
}

输出结果

SUB 0
"UI" 0
SUB 1
SUB 1
"SET" 1
"UI" 1
"UI" 1
SUB 2
SUB 2
"SET" 2
"UI" 2
"UI" 2

这里所有订阅都能正常触发,虽然存在重复调用的情况,但值更新时都会收到回调。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 19:31:03