首页 > 解决方案 > 在启动时将内容附加到 Array

问题描述

您好对以下代码有疑问:

struct ContentView: View {

      @State private var listItems = [Item]()
      let savedItems = UserDefaults.standard.string(forKey: "Items") ?? "error"
      var body: some View {
        NavigationView{

            List{
              ForEach(listItems){ item in
                Text(item.name)
              }
              NavigationLink(
                destination: AddView(listItems: $listItems),
                label: {
                  Text("                 Add")
                    .foregroundColor(.blue)
                })
            }
            .navigationBarTitle("MyApp")
        }
      }
    }

struct AddView: View {
      @State var text:String = ""
      @Binding var listItems: [Item]

      var body: some View {
        VStack{
          TextField("Name", text: $text).padding().background(Color(.systemGray5)).frame(width: 400,alignment: .center).cornerRadius(20)

          Button(action: {
            listItems.append(Item(name: text, image: "Gif"))
            print(listItems)
            UserDefaults.standard.set(listItems, forKey: "Items")
          }, label: {
            Text("Add")
          })
        }
      }
    }

如果我在 AddView 中附加某些内容,我想将其保存在 UserDefaults 中,并在应用程序启动时自动附加。但我不知道该怎么做。你能帮助我吗 ?PS:我正在使用 AppDelegate 和 SceneDelegate。

标签: iosswiftswiftuinsuserdefaultsswiftui-list

解决方案


要在其中保存一些东西,UserDefaults它需要是以下任何一种:

value 参数只能是属性列表对象:NSData、NSString、NSNumber、NSDate、NSArray 或 NSDictionary。对于 NSArray 和 NSDictionary 对象,它们的内容必须是属性列表对象。

查看完整文档

您正在尝试分配Item对象数组,虽然保存数组非常好,但该数组的 Element 类型也需要是文档中提到的类型之一。

您的问题可以使用Codable一致性来解决。

扩展您的项目类型Codable

struct Item: Codable {
    /// your implementation
}

将编码项目保存到 UserDefaults

extension UserDefaults {
    func saveItems(_ items: [Item]) {
        let encoder = JSONEncoder()
        if let data = try? encoder.encode(items) {
            set(data, forKey: "Items")
        }
    }
}

只要您想保存listItems数组,只需调用此方法即可。

UserDefaults.standard.saveItems(listItems)

从 UserDefaults 读取存储的项目

extension UserDefaults {
    func readItems() -> [Item]? {
        guard let data = value(forKey: "Items") as? Data else {
            return nil
        }
        let decoder = JSONDecoder()
        return try? decoder.decode([Item].self, from: data)
    }
}

使用这种方法,您可以在需要时延迟加载项目

@State private var listItems = UserDefaults.standard.readItems() ?? []

推荐阅读