我正在尝试将一个变量设置为UserDefault,以便当用户打开此应用程序(显示问题列表)时,他们会得到上一次在应用程序中最后一次选择的“打包”信息。 / p>
该包由此“ defaultPack”变量确定,该变量设置为UserDefaults,并且该包的数据显示在启动屏幕上。有一个菜单,用户可以选择另一个包,其中的链接带有@Binding变量,该变量在主屏幕上更新该包,该变量应返回到主屏幕,然后也更新UserDefaults。
它似乎正确设置了defaultPack变量,但不能设置UserDefaults,因为每当我重新打开该应用程序时,它将重置为原始默认“ Pack”,而不是用户上次选择的那个。 / strong>
是否有任何需要更改的想法才能正确更新此UserDefaults?
这是一种自定义数据类型,因此我使用的是UserDefaults扩展名,用于对该值进行编码/解码以进行存储。
这是我的带有defaultPack变量的班级:
final class UserInformation: ObservableObject {
@Published var defaultPack: Pack {
didSet {
do {
try UserDefaults.standard.setObject(defaultPack, forKey: "defaultPack")
} catch {
print(error.localizedDescription)
}
}
}
init() {
self.defaultPack = UserDefaults.standard.object(forKey: "defaultPack") as? Pack ?? samplePack
}
}
这是UserDefaults的扩展名,其中包含UserDefaults的可编码/可解码指令
//extension to UserDefaults to include the encodable/decodable instructions for UserDefaults
extension UserDefaults: ObjectSavable {
func setObject<Object>(_ object: Object, forKey: String) throws where Object: Encodable {
let encoder = JSONEncoder()
do {
let data = try encoder.encode(object)
set(data, forKey: forKey)
} catch {
throw ObjectSavableError.unableToEncode
}
}
func getObject<Object>(forKey: String, castTo type: Object.Type) throws -> Object where Object: Decodable {
guard let data = data(forKey: forKey) else { throw ObjectSavableError.noValue }
let decoder = JSONDecoder()
do {
let object = try decoder.decode(type, from: data)
return object
} catch {
throw ObjectSavableError.unableToDecode
}
}
}
这是我的视图,其中包含默认的Pack:
struct PackTopics: View {
@ObservedObject var userInformation: UserInformation
@State var showPacksList: Bool = false
var packsButton: some View {
Button(action: { self.showPacksList.toggle()
}) {
Image(systemName: "tray.full")
.imageScale(.large)
.accessibility(label: Text("Show Packs List"))
.padding()
}
}
var body: some View {
NavigationView {
List {
ForEach(userInformation.defaultPack.sections, id: \.self) { section in
Section(header: SectionHeader(linkedSection: section))
{
ForEach (section.topics, id: \.self) { topic in
TopicLine(linkedTopic: topic)
}
}
}
}
.navigationBarTitle(Text(userInformation.defaultPack.name))
.navigationBarItems(trailing: packsButton)
.sheet(isPresented: $showPacksList) {
PackPage(isPresented: self.$showPacksList, newPack: self.$userInformation.defaultPack)
}
}
}
}
这是与上一个视图中的pack变量绑定的视图,应该更新defaultPack:
struct PackPage: View {
@Binding var isPresented: Bool
@Binding var newPack: Pack
let userDefaults = UserDefaults.standard
var body: some View {
VStack {
HStack {
Text("Question Packs")
.font(.largeTitle)
.fontWeight(.bold)
.padding()
Spacer()
}
Text("Available Packs")
List {
HStack(alignment: .top) {
ForEach(purchasedPacks, id: \.self) { pack in
UnlockedPackTile(tilePack: pack)
.onTapGesture {
print("Originally tapped \(pack.name)")
self.newPack = pack
do {
let userDefaultPack = try self.userDefaults.getObject(forKey: "defaultPack", castTo: Pack.self)
print("Default pack is now set to \(userDefaultPack)")
} catch {
print(error.localizedDescription)
}
self.isPresented.toggle()
}
}
}
}
添加输出 *
2020-06-30 07:04:06.608783-0500 Travel Conversation Starters[2524:131054] [Agent] Received remote injection
2020-06-30 07:04:06.609182-0500 Travel Conversation Starters[2524:131054] [Agent] Create remote injection Mach transport: 6000023ca0d0
2020-06-30 07:04:06.609622-0500 Travel Conversation Starters[2524:131000] [Agent] No global connection handler, using shared user agent
2020-06-30 07:04:06.609840-0500 Travel Conversation Starters[2524:131000] [Agent] Received connection, creating agent
2020-06-30 07:04:07.916795-0500 Travel Conversation Starters[2524:131000] [Agent] Received message: < DTXMessage 0x600002cc4c00 : i2.0e c0 object:(__NSDictionaryI*) {
"products" : <NSArray 0x600000acc200 | 1 objects>
"id" : [0]
"scaleFactorHint" : [2]
"providerName" : "28Travel_Conversation_Starters20ContentView_PreviewsV"
"updates" : <NSArray 0x7fff8062d430 | 0 objects>
} > {
"serviceCommand" : "forwardMessage"
"type" : "display"
}
2020-06-30 07:04:16.447421-0500 Travel Conversation Starters[2524:131000] [Common] _BSMachError: port 9f2f; (os/kern) invalid capability (0x14) "Unable to insert COPY_SEND"
**Originally tapped Family Topics**
**Default pack is now set to Pack(id: 3541AF19-8CDB-4D9B-B261-7194DDD8516E, name: "Family Topics")**
答案 0 :(得分:1)
前段时间,发生了类似的错误。在序列化为Userdefault时,我没有任何错误,但是@Published和didSet属性观察器中存在错误。 您确定要调用didSet吗? 就我而言,当我更改变量时,它没有触发didSet属性观察器。我最终使用了自定义绑定,如下所示:
https://www.hackingwithswift.com/books/ios-swiftui/creating-custom-bindings-in-swiftui。
您还可以尝试将对象复制到temp变量中,然后再次将其重置,以查看是否调用didSet。
我知道这听起来像是一种解决方法,而不是适当的解决方案。但这是了解这里发生的事情的开始。
答案 1 :(得分:1)
@FitzChill,我不知道如何使用此多行代码添加注释,但是检查didSet可以帮助我进行故障排除。看来我的init有问题。
我将其更改为do-catch闭包,现在看来工作正常。
init() {
do {
self.defaultPack = try UserDefaults.standard.getObject(forKey: "defaultPack", castTo: Pack.self)
} catch {
print(error.localizedDescription)
self.defaultPack = samplePack
}
}