如何在 ViewModel 中使用带有自定义类型和 @Published 的 @AppStorage?
Posted
技术标签:
【中文标题】如何在 ViewModel 中使用带有自定义类型和 @Published 的 @AppStorage?【英文标题】:How to use @AppStorage in ViewModel with custom types and @Published? 【发布时间】:2021-09-16 10:15:16 【问题描述】:如何在我的 ViewModel 中使用 @AppStorage 来保存一组自定义类型?如何将@AppStorage 与@Published 属性一起使用?
这是我的示例代码:
型号
struct MyModel: Hashable, Codable
var text: String
var number: Int
查看模型
class ViewModel: ObservableObject
@Published private(set) var myModels = [MyModel]()
@Published private(set) var subscribedMyModels = [MyModel]() // TODO: sync this with AppStorage
func fetchMyModels()
myModels = [
MyModel(text: "Setting", number: 1),
MyModel(text: "Setting", number: 2),
MyModel(text: "Setting", number: 3),
MyModel(text: "Setting", number: 4),
MyModel(text: "Setting", number: 5),
MyModel(text: "Setting", number: 6),
MyModel(text: "Setting", number: 7),
MyModel(text: "Setting", number: 8)
]
func toggleSubscription(for myModel: MyModel)
if subscribedMyModels.contains(myModel)
subscribedMyModels.removeAll(where: $0 == myModel )
else
subscribedMyModels.append(myModel)
查看
struct ContentView: View
@StateObject var viewModel = ViewModel()
@AppStorage(wrappedValue: false, "settings0") private var settings0
var body: some View
List
Section(header: Text("Some Settings"))
Toggle(isOn: $settings0, label:
Text("Setting 0")
)
Section(header: Text("Some other Settings"))
ForEach(viewModel.myModels, id: \.self) myModel in
Button(action:
viewModel.toggleSubscription(for: myModel)
, label:
HStack
HStack
Text(myModel.text)
Text(String(myModel.number))
Spacer()
if viewModel.subscribedMyModels.contains(myModel)
Image(systemName: "checkmark.circle.fill")
else
Image(systemName: "circle")
)
.foregroundColor(.black)
.listStyle(InsetGroupedListStyle())
.onAppear
viewModel.fetchMyModels()
用户界面:
待办事项: 在 AppStorage / UserDefauls 中存储列表“其他一些设置”的检查设置。
【问题讨论】:
在存储到 AppStorage 之前将您的自定义类型编码为字符串或数据(NSUserDefaults 支持的类型)并在加载时解码。 This question 向您展示如何订阅和here is 一种编码选项 【参考方案1】:首先我推荐使用 CoreData 而不是 AppStorage
但要回答你的问题:
将此添加到 ViewModel :
// this is a computed variable which changes with subscribedMyModels changes
var encodedSubscribedMyModels : Data?
let encoder = JSONEncoder()
return try? encoder.encode(subscribedMyModels)
在你的视野中:
.onChange(of: viewModel.encodedSubscribedMyModels, perform: newValue in
// change @AppStore to newValue
settings0 = newValue
)
注意:您需要使用 JSONDecoder 将数据解码回您的数据模型
【讨论】:
以上是关于如何在 ViewModel 中使用带有自定义类型和 @Published 的 @AppStorage?的主要内容,如果未能解决你的问题,请参考以下文章
使用 Ajax 的带有自定义分类法的 Wordpress 多个自定义帖子类型过滤器 - 所有新创建的帖子都不会在响应中显示