CoreData/SQLite/FMDB

SwiftUI中使用CoreData

2022-03-13  本文已影响0人  凉风起君子意如何

今天要学习的是如何在SwiftUI中使用CoreData。

知识点:
1、已有项目添加CoreData
2、SwiftUI中处理CoreData中的entity,包括读取,添加,删除
3、SwiftUI中保存并读取环境变量

学习链接来自该篇文章,讲的很细

CoreData

什么是CoreData?它有什么作用?它的优势?网上有很多相关资料,这里就不多说了。可以大致的看下如下总体结构图 引用自该文章

func sceneDidEnterBackground(_ scene: UIScene) {
        saveContext()
    }
//MARK: -CoreData
    lazy var persistentContainer: NSPersistentContainer = {
        let container = NSPersistentContainer(name: "CoredataSwiftUI")
        container.loadPersistentStores { _, error in
            if let error = error as NSError? {
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        }
        return container
    }()
    
    func saveContext() {
        let context = persistentContainer.viewContext
        if context.hasChanges {
            do {
                try context.save()
            } catch  {
                let error = error as NSError
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        }
    }

3、打开xcdatamodeld文件,添加相应的model也就是entity。这里我们创建Movie模型


SwiftUI使用CoreData

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        let context = persistentContainer.viewContext
        let contentView = MovieList().environment(\.managedObjectContext, context)
        
        guard let windowScene = (scene as? UIWindowScene) else { return }
        window = UIWindow(windowScene: windowScene)
        window?.rootViewController = UIHostingController(rootView: contentView)
        window?.makeKeyAndVisible()
    }
import SwiftUI

struct MovieList: View {
    // 读取viewContext,赋值给managedObjectContext属性
    @Environment(\.managedObjectContext) var managedObjectContext
    // 读取Movie对象集,赋值给movies数组。没有要求传入任何name
    @FetchRequest(entity: Movie.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \Movie.title, ascending: true)]) var movies: FetchedResults<Movie>
    
    @State var isPresented = false

    var body: some View {
      NavigationView {
        List {
          ForEach(movies, id: \.title) {
            MovieRow(movie: $0)
          }
          .onDelete(perform: deleteMovie)
        }
        .sheet(isPresented: $isPresented) {
          AddMovieView { title, genre, release in
            self.addMovie(title: title, genre: genre, releaseDate: release)
            self.isPresented = false
          }
        }
        .navigationBarTitle(Text("Fave Flicks"))
        .navigationBarItems(trailing:
          Button(action: { self.isPresented.toggle() }) {
            Image(systemName: "plus")
          }
        )
      }
    }

    // 删除一个movie,并更新coredata数据库
    func deleteMovie(at offsets: IndexSet) {
      // 1.
      offsets.forEach { index in
        // 2.
        let movie = self.movies[index]

        // 3.
        self.managedObjectContext.delete(movie)
      }

      // 4.
      saveContext()
    }

    // 添加一个movie,并更新保存数据库
    func addMovie(title: String, genre: String, releaseDate: Date) {
      // 1 从viewContext获取一个Movie对象
      let newMovie = Movie(context: managedObjectContext)

      // 2
      newMovie.title = title
      newMovie.genre = genre
      newMovie.releaseDate = releaseDate

      // 3
      saveContext()
    }


    func saveContext() {
      do {
        try managedObjectContext.save()
      } catch {
        print("Error saving managed object context: \(error)")
      }
    }
}

SwiftUI中使用CoreData,总结几个点
1、如何将内存中管理coredata的persistentContainer.viewContext传给相应的view。当然在非SwiftUI项目中,可能直接在AppDelegate定义成相应的熟悉,之后用的地方通过AppDelegate获取即可
2、SwiftUI view中如何获取viewContext,继而通过viewContext处理添加或删除并保存更新操作
3、如何读取coredata里面相应的entity

SwiftUI中保存并读取环境变量

从上面的代码,很容易发现SwiftUI中是如何保存并读取环境变量的。
保存设置环境变量:
SceneDelegate.swift文件

let context = persistentContainer.viewContext
        let contentView = MovieList().environment(\.managedObjectContext, context)

从当前环境中读取变量:
MovieList.swift文件

// 读取viewContext,赋值给managedObjectContext属性
    @Environment(\.managedObjectContext) var managedObjectContext

End

对于移动端中小型项目来说一个是container,已经够用,也建议用一个。对于多个数据库container使用场景,目前还没接触到。

2、代码里设置viewContext

添加红框代码
参考该篇文章,解析很详细,以及hash的介绍
上一篇下一篇

猜你喜欢

热点阅读