gpt4 book ai didi

SwiftUI:如何持久化 @EnvironmentObject 变量?

转载 作者:行者123 更新时间:2023-12-03 09:24:50 24 4
gpt4 key购买 nike

我想要一个变量作为 EnvironmentObject 并且我也希望它被持久化,这样每次我重新启动我的应用程序时它都是一样的。

为此,我已经创建了以下 propertyWrapper:

import Foundation

@propertyWrapper
struct UserDefault<T: Codable> {
let key: String
let defaultValue: T

var wrappedValue: T {
get {
if let encodedValue = UserDefaults.standard.object(forKey: key) as? Data {
let decoder = JSONDecoder()
let decodedValue = try! decoder.decode(T.self, from: encodedValue)
return decodedValue
} else {
return defaultValue
}
} set {
let encoder = JSONEncoder()
let encodedValue = try! encoder.encode(newValue)
UserDefaults.standard.set(encodedValue, forKey: key)
}
}
}

但是已经有一个属性包装器意味着我不能使用来自Combine 的@Published 属性包装器。 (在一个变量上使用两个属性包装器听起来不是一个好主意,而且我还没有找到让它工作的方法。)

我通过定制 objectWillChange 解决了这个问题让常量并调用它的 .send(input:) willSet 中的每个变量的方法。

所以这是我的 DataStore 类:

import SwiftUI
import Combine

final class DataStore: ObservableObject {
let objectWillChange = PassthroughSubject<DataStore, Never>()

@UserDefault(key: "the text", defaultValue: "Hello world!")
var text: String {
willSet {
objectWillChange.send(self)
}
}
}

这是我的观点:

struct StartView : View {
@EnvironmentObject var dataStore: DataStore
var body: some View {
VStack {
TextField("Enter text", text: $dataStore.text)
Button("Reset text", action: {
self.dataStore.text = "Hello World!"
})
}
}
}

但不知何故,我真的相信应该有一种比制作自定义 objectWillChange 更漂亮的方式。有没有办法制作一个涵盖持久化和“发布”的单一属性包装器?或者我应该做一些完全不同的事情来达到我的目标?

谢谢!

最佳答案

根据推测的 Genetec Tech ( https://medium.com/genetec-tech/property-wrappers-in-swift-5-1-the-missing-published-implementation-1a466ebcf660 ) 实现,您可以将两个属性包装器合并为一个 @PublishedUserDefault。

例子:

这是 UserDefaults 的普通 propertyWrapper

@propertyWrapper
struct UserDefault<T> {
let key: String
let defaultValue: T

var wrappedValue: T {
get {
UserDefaults.standard.value(forKey: key) as? T ?? defaultValue
} set {
UserDefaults.standard.set(newValue, forKey: key)
}
}
}

当 UserDefaults.set(_ ,forKey:) 被调用时,这个 viewModel 也会更新。

final class UserSettings: ObservableObject {
let objectWillChange = ObservableObjectPublisher()

@UserDefault(key: "text", defaultValue: "")
var text: String

private var notificationSubscription: AnyCancellable?

init() {
notificationSubscription = NotificationCenter.default.publisher(for: UserDefaults.didChangeNotification).sink { _ in
self.objectWillChange.send()
}
}
}

关于SwiftUI:如何持久化 @EnvironmentObject 变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57428780/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com