djk3000 / ME

4 stars 2 forks source link

SwiftUI-CoreData在MVVM中的应用 #107

Open djk3000 opened 1 year ago

djk3000 commented 1 year ago

CoreData

在iOS本地做持久化的时候用到有两种方法,一个是UserDefaults,另一个就是CoreData了,这两个的都能保存在本地。 UserDefaults一般存储比较小的信息,一些设置等等,不适合大型数据集。 CoreData比较类似SQLLite,一个小型的数据库,存储一些比较大的数据。

使用方法

  1. 新建一个CoreData中的DataModel,然后AddEntity,Entity名字之后有用,然后新建Attribute,我添加了一个name的String。
  2. 创建一个ViewModel:

    class CoreDataViewModel: ObservableObject {
    let container: NSPersistentContainer
    @Published var saveEntities: [FriutEntity] = []
    
    //初始化CoreData
    init(){
        container = NSPersistentContainer(name: "FruitsContainer")  //这是AddEntity的名字,不能有拼错
        container.loadPersistentStores { description, error in
            if let error = error {
                print("Load CoreData error--\(error)")
            } else {
                print("Successfully loading CoreData")
            }
        }
        fetchFruits()
    }
    
    func fetchFruits() {
        let request = NSFetchRequest<FriutEntity>(entityName: "FriutEntity")
        do {
            try saveEntities = container.viewContext.fetch(request)
        } catch let error {
            print("Error fetch \(error)")
        }
    }
    
    //CoreData中添加数据
    func addFruit(text: String) {
        let newFruit = FriutEntity(context: container.viewContext)
        newFruit.name = text
        saveData()
    }
    
     //CoreData中删除数据
    func deleteFruit(indexSet: IndexSet) {
        guard let index = indexSet.first else { return }
        let entity = saveEntities[index]
        container.viewContext.delete(entity)
        saveData()
    }
    
     //CoreData中更改数据
    func updateFruit(entity: FriutEntity) {
        let current = entity.name ?? ""
        let newName = current + "!"
        entity.name = newName
        saveData()
    }
    
    //每次操作完都需要运行一下save方法
    func saveData() {
        do {
            try container.viewContext.save()
            fetchFruits()
        } catch let error {
            print("Save error \(error)")
        }
    }
    }
  3. 然后就可以使用这个ViewModel的方法操作CoreData了。

    struct CoreDataBootcamp: View {
    @StateObject var vm: CoreDataViewModel = CoreDataViewModel()
    @State var textFieldText: String = ""
    var body: some View {
        NavigationView {
            VStack (spacing: 20) {                
                TextField("Add ..", text: $textFieldText)
                    .font(.title)
                    .padding(.leading)
                    .foregroundColor(.white)
                    .frame(height: 55, alignment: .center)
                    .background(.gray)
                    .cornerRadius(10)
                    .padding(.horizontal)
    
                Button {
                    guard !textFieldText.isEmpty else { return }
                    vm.addFruit(text: textFieldText)
                    textFieldText = ""
                } label: {
                    Text("添加")
                }
    
                List {
                    ForEach(vm.saveEntities) { entity in
                        Text(entity.name ?? "No Name")
                            .onTapGesture {
                                vm.updateFruit(entity: entity)
                            }
                    }
                    .onDelete(perform: vm.deleteFruit(indexSet:))
                }
                .listStyle(.plain)
            }
            .navigationTitle("Fruits")
        }
    }
    }

参考资料

UserDefaults or Core Data? How to use Core Data with MVVM