SwiftUI中使用CoreData

今天要學(xué)習(xí)的是如何在SwiftUI中使用CoreData宫仗。

知識點(diǎn):
1吩抓、已有項(xiàng)目添加CoreData
2、SwiftUI中處理CoreData中的entity锌俱,包括讀取炭臭,添加永脓,刪除
3、SwiftUI中保存并讀取環(huán)境變量

學(xué)習(xí)鏈接來自該篇文章鞋仍,講的很細(xì)

CoreData

什么是CoreData常摧?它有什么作用?它的優(yōu)勢威创?網(wǎng)上有很多相關(guān)資料落午,這里就不多說了谎懦。可以大致的看下如下總體結(jié)構(gòu)圖 引用自該文章

  • 已有項(xiàng)目添加CoreData
    添加CoreData方式有二板甘,一是新創(chuàng)建項(xiàng)目時(shí)党瓮,勾選CoreData盐类,創(chuàng)建完項(xiàng)目后,自動添加了涉及的相關(guān)功能呛谜。二就是下面要說的在跳,如何在已有的項(xiàng)目添加CoreData,主要分下面三步:
    1隐岛、手動創(chuàng)建xcdatamodeld文件猫妙,文件名稱一般命名工程名稱



    2、在SeneDelegate.swift里添加相應(yīng)代碼聚凹。其實(shí)就是創(chuàng)建并設(shè)置container割坠。

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文件妒牙,添加相應(yīng)的model也就是entity彼哼。這里我們創(chuàng)建Movie模型


SwiftUI使用CoreData

  • 設(shè)置根視圖CoreData viewContext.如下代碼
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()
    }
  • 通過讀取環(huán)境變量中的CoreData viewContext,執(zhí)行后續(xù)添加/刪除保存湘今。這里有個(gè)疑問點(diǎn) 在讀取Movie對象的時(shí)候敢朱,沒有告訴到底是哪個(gè)container,難道一個(gè)工程下就只能存在一個(gè)container摩瞎?拴签??核心代碼如下旗们,注意看注釋
import SwiftUI

struct MovieList: View {
    // 讀取viewContext蚓哩,賦值給managedObjectContext屬性
    @Environment(\.managedObjectContext) var managedObjectContext
    // 讀取Movie對象集,賦值給movies數(shù)組上渴。沒有要求傳入任何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")
          }
        )
      }
    }

    // 刪除一個(gè)movie岸梨,并更新coredata數(shù)據(jù)庫
    func deleteMovie(at offsets: IndexSet) {
      // 1.
      offsets.forEach { index in
        // 2.
        let movie = self.movies[index]

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

      // 4.
      saveContext()
    }

    // 添加一個(gè)movie,并更新保存數(shù)據(jù)庫
    func addMovie(title: String, genre: String, releaseDate: Date) {
      // 1 從viewContext獲取一個(gè)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驰贷,總結(jié)幾個(gè)點(diǎn)
1盛嘿、如何將內(nèi)存中管理coredata的persistentContainer.viewContext傳給相應(yīng)的view。當(dāng)然在非SwiftUI項(xiàng)目中括袒,可能直接在AppDelegate定義成相應(yīng)的熟悉次兆,之后用的地方通過AppDelegate獲取即可
2、SwiftUI view中如何獲取viewContext锹锰,繼而通過viewContext處理添加或刪除并保存更新操作
3芥炭、如何讀取coredata里面相應(yīng)的entity

SwiftUI中保存并讀取環(huán)境變量

從上面的代碼漓库,很容易發(fā)現(xiàn)SwiftUI中是如何保存并讀取環(huán)境變量的。
保存設(shè)置環(huán)境變量:
SceneDelegate.swift文件

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

從當(dāng)前環(huán)境中讀取變量:
MovieList.swift文件

// 讀取viewContext园蝠,賦值給managedObjectContext屬性
    @Environment(\.managedObjectContext) var managedObjectContext

End

  • 還記的上面那個(gè)疑問點(diǎn)嗎渺蒿?
    疑問點(diǎn) 在讀取Movie對象的時(shí)候,沒有告訴到底是哪個(gè)container彪薛,難道一個(gè)工程下就只能存在一個(gè)container茂装??善延?
    查看官方文檔找到了答案:

    如上步驟搜索NSFetchRequest會發(fā)現(xiàn)這么一段話少态,當(dāng)然你還會發(fā)現(xiàn)其它讀取entity時(shí)的一些重要設(shè)置,如從什么地方開始讀易遣,最大讀多少彼妻,應(yīng)該讀哪個(gè)store,返回哪些數(shù)據(jù)等

對于移動端中小型項(xiàng)目來說一個(gè)是container豆茫,已經(jīng)夠用侨歉,也建議用一個(gè)。對于多個(gè)數(shù)據(jù)庫container使用場景揩魂,目前還沒接觸到幽邓。

  • 如何避免讀取重復(fù)的數(shù)據(jù)呢? 例如肤京,一個(gè)學(xué)生列表中有很多同名的學(xué)生 分?jǐn)?shù)可能不同颊艳,現(xiàn)在不需要重復(fù)讀取多個(gè)同名學(xué)生信息。如下2步設(shè)置即可
    1忘分、改動xcdatamodeld文件


    約束name屬性不重名

2棋枕、代碼里設(shè)置viewContext

添加紅框代碼

參考該篇文章,解析很詳細(xì)妒峦,以及hash的介紹

  • CoreData常用的幾個(gè)謂詞重斑,即篩選器


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市肯骇,隨后出現(xiàn)的幾起案子窥浪,更是在濱河造成了極大的恐慌,老刑警劉巖笛丙,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件漾脂,死亡現(xiàn)場離奇詭異,居然都是意外死亡胚鸯,警方通過查閱死者的電腦和手機(jī)骨稿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人坦冠,你說我怎么就攤上這事形耗。” “怎么了辙浑?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵激涤,是天一觀的道長。 經(jīng)常有香客問我判呕,道長倦踢,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任侠草,我火速辦了婚禮硼一,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘梦抢。我一直安慰自己,他們只是感情好愧哟,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布奥吩。 她就那樣靜靜地躺著,像睡著了一般蕊梧。 火紅的嫁衣襯著肌膚如雪霞赫。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天肥矢,我揣著相機(jī)與錄音端衰,去河邊找鬼。 笑死甘改,一個(gè)胖子當(dāng)著我的面吹牛旅东,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播十艾,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼抵代,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了忘嫉?” 一聲冷哼從身側(cè)響起荤牍,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎庆冕,沒想到半個(gè)月后康吵,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡访递,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年晦嵌,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,040評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡耍铜,死狀恐怖邑闺,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情棕兼,我是刑警寧澤陡舅,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站伴挚,受9級特大地震影響靶衍,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜茎芋,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一颅眶、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧田弥,春花似錦涛酗、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至只泼,卻和暖如春剖笙,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背请唱。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工弥咪, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人十绑。 一個(gè)月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓聚至,卻偏偏與公主長得像,于是被迫代替她去往敵國和親孽惰。 傳聞我的和親對象是個(gè)殘疾皇子晚岭,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評論 2 355

推薦閱讀更多精彩內(nèi)容