首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >iOS小部件不会第一次在主屏幕中读取UserDeafults值

iOS小部件不会第一次在主屏幕中读取UserDeafults值
EN

Stack Overflow用户
提问于 2021-07-11 19:38:26
回答 2查看 104关注 0票数 0

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

代码语言:javascript
复制
let appGroupId = "group.com.myAppGroupId"
Text(UserDefaults(suiteName: appGroupId)!.object(forKey: "githubId") as? String ?? "??")

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

我猜不出原因。

+添加更多代码

实际上,我使用属性包装将我的githubId定义为UserDefaults,如下所示。

代码语言:javascript
复制
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?
}

我的属性包装器是这样的。

代码语言:javascript
复制
@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的值。

代码语言:javascript
复制
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的长版本。

EN

Stack Overflow用户

回答已采纳

发布于 2021-07-11 23:06:25

.sink不能在窗口小部件中工作。

在设置时间线时,必须完成要在小部件中显示的任何内容。窗口小部件不会监听更改。

当有变化时,你必须从应用程序中重新加载小部件时间线。将每个时间线条目视为屏幕截图。

WidgetCenter.shared.reloadAllTimelines()

重新加载是计量的,所以一定要检查一下,不要过多地重新加载。

票数 0
EN
查看全部 2 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68335835

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档