Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在swiftUI中创建可编辑对象的动态列表,并将其存储在手机中_Swift_Swiftui - Fatal编程技术网

在swiftUI中创建可编辑对象的动态列表,并将其存储在手机中

在swiftUI中创建可编辑对象的动态列表,并将其存储在手机中,swift,swiftui,Swift,Swiftui,我试图在SwiftUI中创建一个可编辑对象列表。这是我的想法 首先,可编辑项如下: struct Item: Identifiable { var id: UUID var ItemNum: Int var notes: String = "" } final class ItemStore: ObservableObject { @Published var items: [Item] = [ .init(id: .init(

我试图在SwiftUI中创建一个可编辑对象列表。这是我的想法

首先,可编辑项如下:

struct Item: Identifiable {

   var id: UUID
   var ItemNum: Int
   var notes: String = ""

}

final class ItemStore: ObservableObject {
    @Published var items: [Item] = [
        .init(id: .init(), ItemNum: 55),
        .init(id: .init(), ItemNum: 57),
        .init(id: .init(), ItemNum: 87)
    ]
}
之后,我创建了一个从ItemStore获取数据的列表:

struct ItemView: View {

@State private var editMode = EditMode.inactive
@ObservedObject var store: ItemStore

var body: some View {
    NavigationView {
        List {
            ForEach(store.items.indexed(), id:\.1.id) {index, item in
                NavigationLink(destination: ItemEditingView(item: self.$store.items[index])) {
                    VStack(alignment: .leading) {
                        Text("Item Num: \(item.itemNum)")
                    }
                }
            }
        }
        //.onAppear(perform: store.fetch)  // want to fetch the data from the store whenever the list appear, however, no idea to perform the function?!
        .navigationBarTitle("Items")
        .navigationBarItems( trailing: addButton)
        .environment(\.editMode, $editMode)
    }
    
}

private var addButton: some View {
    switch editMode {
    case .inactive:
        return AnyView(Button(action: onAdd) { Image(systemName: "plus") })
    default:
        return AnyView(EmptyView())
    }
}

private func onAdd() {
    store.items.append(Item(id: UUID(), itemNum: 10)) 
}
}

编辑视图:

struct ItemEditingView: View {

@Environment(\.presentationMode) var presentation
@Binding var item: Item

var body: some View {
    Form {
        Section(header: Text("Item")) {
            Text(Text("Item Num: \(item.itemNum)"))
            TextField("Type something...", text: $item.notes)
        }
        Section {
            Button("Save") {
                self.presentation.wrappedValue.dismiss()
            }
        }
    }.navigationTitle(Text("Item Num: \(item.itemNum)"))
}
}

我的问题是:

  • 我想从附件的“存储”中获取数据。但它失败了
  • 退出应用程序后,以前的所有数据都消失了。我怎样才能让它们留在我的应用程序中,即使应用程序是kill

  • 首先是您的第二个问题:在存储(持久化数据)方面,您有很多选择。最简单的方法是将其存储在
    UserDefaults
    中,我将在示例中展示。您还可以选择使用CoreData,这将是一个更需要设置的过程,但稍后将为您提供更健壮的解决方案。还有更多的选项,如领域、Firebase、SQLite等

    
    struct Item: Identifiable, Codable {
        var id: UUID = UUID()
        var itemNum: Int
        var notes: String = ""
        
    }
    
    final class ItemStore: ObservableObject {
        @Published var items: [Item] = [] {
            didSet {
                let encoder = JSONEncoder()
                if let encoded = try? encoder.encode(items) {
                    UserDefaults.standard.set(encoded, forKey: "savedItems")
                }
            }
        }
        
        let defaultValues : [Item] = [
            .init(itemNum: 55),
            .init(itemNum: 57),
            .init(itemNum: 87)
        ]
        
        func fetch() {
            let decoder = JSONDecoder()
            if let savedItems = UserDefaults.standard.object(forKey: "savedItems") as? Data,
               let loadedItems = try? decoder.decode([Item].self, from: savedItems) {
                items = loadedItems
            } else {
                items = defaultValues
            }
        }
    }
    
    struct ContentView : View {
        @State private var editMode = EditMode.inactive
        @ObservedObject var store: ItemStore = ItemStore()
        
        var body: some View {
            NavigationView {
                List {
                    ForEach(Array(store.items.enumerated()), id:\.1.id) { (index,item) in
                        NavigationLink(destination: ItemEditingView(item: self.$store.items[index])) {
                            VStack(alignment: .leading) {
                                Text("Item Num: \(item.itemNum)")
                            }
                        }
                    }
                }
                .onAppear(perform: store.fetch)
                .navigationBarTitle("Items")
                .navigationBarItems( trailing: addButton)
                .environment(\.editMode, $editMode)
            }
            
        }
        
        private var addButton: some View {
            switch editMode {
            case .inactive:
                return AnyView(Button(action: onAdd) { Image(systemName: "plus") })
            default:
                return AnyView(EmptyView())
            }
        }
        
        private func onAdd() {
            store.items.append(Item(id: UUID(), itemNum: 10))
        }
    }
    
    
    struct ItemEditingView: View {
        
        @Environment(\.presentationMode) var presentation
        @Binding var item: Item
        
        var body: some View {
            Form {
                Section(header: Text("Item")) {
                    Text("Item Num: \(item.itemNum)")
                    TextField("Type something...", text: $item.notes)
                }
                Section {
                    Button("Save") {
                        self.presentation.wrappedValue.dismiss()
                    }
                }
            }.navigationTitle(Text("Item Num: \(item.itemNum)"))
        }
    }
    
    
    关于第一个问题,
    fetch
    失败的原因是您没有
    fetch
    方法。另外,由于每次创建
    ItemStore
    时才填充
    items
    数组,因此没有任何东西可获取

    注:

  • Item
    现在符合
    Codable
    ——这就是允许它转换为可以从UserDefaults保存/加载的值的原因
  • fetch
    现在在appear上调用
  • 每次更改数据时,都会调用
    didSet
    ,将新数据保存到UserDefaults
  • 在原始代码中有许多拼写错误和简单的东西是无法编译的,所以请确保这些更改得到了反映。其中包括:
    枚举的
    而不是
    ForEach
    中的
    索引的
    ,不调用
    文本(文本(
    带有嵌套值,使用整个
    itemNum
    的相同大小写,等等

  • 重要信息:测试此功能时,请确保在更改后几秒钟将数据保存到UserDefaults中,然后关闭应用程序并再次打开它。

    第二点取决于您的选择,如果您的数据存储很大(不是很大),Personal和have relationships,选项是使用CoreData,但如果您想要类似于UserDefault的功能,并且数据不是个人的,则swiftUI将提供@AppStorage属性。