首页 > 解决方案 > iOS Widget 在主屏幕第一次不读取 UserDeafults 值

问题描述

我使用 UserDefaults 的值设置了我的 WidgetView。为了在小部件和核心应用程序之间共享数据,我已经设置了 appGroup。

let appGroupId = "group.com.myAppGroupId"
Text(UserDefaults(suiteName: appGroupId)!.object(forKey: "githubId") as? String ?? "??")

它在预览中显示良好,但是当我将其添加到主屏幕时,它无法读取属性。在同样的情况下,当我重建应用程序 (cmd+r) 时,主屏幕中的小部件可以很好地读取 UserDefaults 的值。

我猜不出原因。

+++++ 添加更多代码

实际上,我githubId使用属性包装器将我的定义为 UserDefaults。

extension UserDefaults {
    enum Key: String {
        case githubId
    }
  
    static let shared: UserDefaults = {
        let appGroupId = "group.com.myAppGroupId"
        return UserDefaults(suiteName: appGroupId)!
    }()

    @UserDefault(key: .githubId)
    static var githubId: String?
}

我的属性包装器看起来像这样。

@propertyWrapper
struct UserDefault<Value> {
    let key: String
    let defaultValue: Value
    var container: UserDefaults = .shared
    private let publisher = PassthroughSubject<Value, Never>()
    
    var wrappedValue: Value {
        get {
            return container.object(forKey: key) as? Value ?? defaultValue
        }
        set {
            if let optional = newValue as? AnyOptional, optional.isNil {
                container.removeObject(forKey: key)
            } else {
                container.set(newValue, forKey: key) //this is where I set my value
            }
            publisher.send(newValue)
        }
    }

    var projectedValue: AnyPublisher<Value, Never> {
        return publisher.eraseToAnyPublisher()
    }
}

extension UserDefault where Value: ExpressibleByNilLiteral {
    init(key: UserDefaults.Key, _ container: UserDefaults = .shared) {
        self.init(key: key.rawValue, defaultValue: nil, container: container)
    }
}

LoginViewModel中,我设置了 githubId 值。

class LoginViewModel: ObservableObject {
    @Published var githubId = UserDefaults.githubId ?? ""
    private var subscriptions = Set<AnyCancellable>()
    
    init() {
        $githubId
            .sink { githubId in
                UserDefaults.githubId = githubId
            }
            .store(in: &subscriptions)
    }
}

最后我在我的应用程序中使用这个值,并使用小部件扩展UserDefaults.githubId

我上面写的代码 ( UserDefaults(suiteName: appGroupId)!.object(forKey: "githubId")) 的长版本 UserDefaults.githubId

标签: iosswiftswiftuiwidgetuserdefaults

解决方案


可以选择使用 @AppStorage 吗?您的代码可能如下所示:

@AppStorage('githubId) var id:String
Text(id)

推荐阅读