AVt天堂网 手机版,亚洲va久久久噜噜噜久久4399,天天综合亚洲色在线精品,亚洲一级Av无码毛片久久精品

當(dāng)前位置:首頁(yè) > 科技  > 軟件

Swift 定制 Core Data 遷移

來(lái)源: 責(zé)編: 時(shí)間:2024-05-17 17:48:49 171觀看
導(dǎo)讀前言隨著應(yīng)用程序和用戶群的增長(zhǎng),你需要添加新功能,刪除其他功能,并改變應(yīng)用程序的工作方式。這是軟件開(kāi)發(fā)生命周期的自然結(jié)果,我們應(yīng)該接受。隨著應(yīng)用程序的發(fā)展,你的數(shù)據(jù)模型也會(huì)發(fā)生變化。你需要更改數(shù)據(jù)結(jié)構(gòu)的方式,以適

Lxr28資訊網(wǎng)——每日最新資訊28at.com

前言

隨著應(yīng)用程序和用戶群的增長(zhǎng),你需要添加新功能,刪除其他功能,并改變應(yīng)用程序的工作方式。這是軟件開(kāi)發(fā)生命周期的自然結(jié)果,我們應(yīng)該接受。Lxr28資訊網(wǎng)——每日最新資訊28at.com

隨著應(yīng)用程序的發(fā)展,你的數(shù)據(jù)模型也會(huì)發(fā)生變化。你需要更改數(shù)據(jù)結(jié)構(gòu)的方式,以適應(yīng)新功能,同時(shí)確保用戶不會(huì)在不同版本之間丟失任何數(shù)據(jù)。如果你使用 Core Data 在應(yīng)用程序中持久化信息,那么 Core Data 遷移就會(huì)發(fā)揮作用。Lxr28資訊網(wǎng)——每日最新資訊28at.com

什么是 Core Data 遷移?

Core Data 遷移是將數(shù)據(jù)模型從一個(gè)版本更新到另一個(gè)版本的過(guò)程,因?yàn)閿?shù)據(jù)的形狀發(fā)生了變化(例如,添加或刪除新屬性)。Lxr28資訊網(wǎng)——每日最新資訊28at.com

在大多數(shù)情況下,Core Data 將自動(dòng)處理遷移過(guò)程。但是,有些情況下,你需要通過(guò)提供一個(gè)映射模型來(lái)自定義遷移過(guò)程,告訴 Core Data 究竟如何從源模型遷移到目標(biāo)模型中的每個(gè)屬性和實(shí)體。Lxr28資訊網(wǎng)——每日最新資訊28at.com

甚至有些情況下,映射模型是不夠的,你需要編寫(xiě)自定義遷移策略來(lái)處理特定情況。這是本文要重點(diǎn)討論的情況。Lxr28資訊網(wǎng)——每日最新資訊28at.com

示例

讓我們考慮一個(gè)應(yīng)用程序,在 Core Data 棧中存儲(chǔ)表示音樂(lè)曲目的對(duì)象。模型非常簡(jiǎn)單,只包含一個(gè)實(shí)體:Track,Track.swift 代碼如下:Lxr28資訊網(wǎng)——每日最新資訊28at.com

Copy codeTrack.swiftimport Foundationimport CoreData@objc(Track)public class Track: NSManagedObject, Identifiable {    @nonobjc public class func fetchRequest() -> NSFetchRequest<Track> {        return NSFetchRequest<Track>(entityName: "Track")    }    @NSManaged public var imageURL: String?    @NSManaged public var json: String?    @NSManaged public var lastPlayedAt: Date?    @NSManaged public var title: String?    @NSManaged public var artistName: String?}

上面的 Track 實(shí)體有五個(gè)屬性:Lxr28資訊網(wǎng)——每日最新資訊28at.com

  • imageURL:表示曲目封面圖像的 URL 的字符串。
  • json:表示來(lái)自服務(wù)器的原始 JSON 數(shù)據(jù)響應(yīng)的字符串。
  • lastPlayedAt:表示上次播放曲目的日期。
  • title:表示曲目的標(biāo)題的字符串。
  • artistName:表示藝術(shù)家的名稱的字符串。

Core Data 棧不會(huì)與 iCloud 同步,并具有以下設(shè)置,CoreDataStack.swift 文件代碼如下:Lxr28資訊網(wǎng)——每日最新資訊28at.com

Copy codeCoreDataStack.swiftimport CoreDatastruct PersistenceController {    static let shared = PersistenceController()    let container: NSPersistentContainer    init(inMemory: Bool = false) {        container = NSPersistentContainer(name: "CustomMigration")        if inMemory {            container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")        }        container.viewContext.automaticallyMergesChangesFromParent = true        if let description = container.persistentStoreDescriptions.first {            description.shouldMigrateStoreAutomatically = true            description.shouldInferMappingModelAutomatically = false        }        container.loadPersistentStores(completionHandler: { (storeDescription, error) in            if let error = error as NSError? {                fatalError("Unresolved error /(error), /(error.userInfo)")            }        })    }}

如果你仔細(xì)觀察上面的示例,你會(huì)注意到我們告訴 Core Data 自動(dòng)遷移存儲(chǔ),因?yàn)槲覀儾幌胱鰸u進(jìn)式遷移,這種遷移速度慢得多且更復(fù)雜,并且我們還告訴 Core Data 不要自動(dòng)推斷映射模型,這意味著我們將不得不為每個(gè)遷移提供一個(gè)映射模型文件,并且可以允許我們自定義這個(gè)過(guò)程。Lxr28資訊網(wǎng)——每日最新資訊28at.com

持久化了一首歌曲后,使用 Core Data Lab 檢查數(shù)據(jù)庫(kù),我們可以看到屬性被相應(yīng)保存:Lxr28資訊網(wǎng)——每日最新資訊28at.com

Lxr28資訊網(wǎng)——每日最新資訊28at.com

更新模型

當(dāng)前版本的模型存在一些可擴(kuò)展性問(wèn)題:Lxr28資訊網(wǎng)——每日最新資訊28at.com

  • 模型僅允許每個(gè)曲目有一個(gè)藝術(shù)家,而實(shí)際上,一個(gè)曲目可以有多個(gè)藝術(shù)家。
  • 模型存儲(chǔ)一個(gè)表示曲目數(shù)據(jù)的原始 JSON 字符串,這不太高效,當(dāng)應(yīng)用程序需要解析 JSON 字符串以顯示曲目數(shù)據(jù)以獲取藝術(shù)家列表時(shí),可能會(huì)導(dǎo)致性能問(wèn)題。

為了解決這些問(wèn)題,讓我們刪除 artistName 和 json 屬性,采用一個(gè)新的 Artist 實(shí)體,該實(shí)體將與 Track 實(shí)體建立一對(duì)多的關(guān)系。Lxr28資訊網(wǎng)——每日最新資訊28at.com

Artist 實(shí)體將具有一個(gè)表示藝術(shù)家名稱的 name 屬性,以及 id 和 imageURL 屬性,我們將從原始 JSON 字符串中獲取它們。Lxr28資訊網(wǎng)——每日最新資訊28at.com

創(chuàng)建一個(gè)新的模型版本

首先,讓我們通過(guò)選擇 .xcdatamodeld 文件,然后從菜單欄中選擇 Editor > Add Model Version... 來(lái)創(chuàng)建一個(gè)新的模型版本。Lxr28資訊網(wǎng)——每日最新資訊28at.com

Lxr28資訊網(wǎng)——每日最新資訊28at.com

給它起一個(gè)名稱,并以第一個(gè)模型版本為基礎(chǔ):Lxr28資訊網(wǎng)——每日最新資訊28at.com

Lxr28資訊網(wǎng)——每日最新資訊28at.com

現(xiàn)在,讓我們創(chuàng)建 Artist 實(shí)體并添加所有字段:Lxr28資訊網(wǎng)——每日最新資訊28at.com

Lxr28資訊網(wǎng)——每日最新資訊28at.com

也讓我們?yōu)樾碌?nbsp;Artist 實(shí)體創(chuàng)建 NSManagedObject 子類(lèi),Artist.swift 代碼如下:Lxr28資訊網(wǎng)——每日最新資訊28at.com

Copy codeimport Foundationimport CoreData@objc(Artist)public class Artist: NSManagedObject, Identifiable {    @nonobjc public class func fetchRequest() -> NSFetchRequest<Artist> {        return NSFetchRequest<Artist>(entityName: "Artist")    }    @NSManaged public var name: String?    @NSManaged public var id: String?    @NSManaged public var imageURL: String?    @NSManaged public var tracks: NSSet?    @objc(addTracksObject:)    @NSManaged public func addToTracks(_ value: Track)    @objc(removeTracksObject:)    @NSManaged public func removeFromTracks(_ value: Track)    @objc(addTracks:)    @NSManaged public func addToTracks(_ values: NSSet)    @objc(removeTracks:)    @NSManaged public func removeFromTracks(_ values: NSSet)}

正如你在上面的示例中看到的那樣,我們將向 Track 實(shí)體添加一個(gè)對(duì)多的 artists 關(guān)系,還將向 Artist 實(shí)體添加一個(gè)對(duì)多的 tracks 關(guān)系。Lxr28資訊網(wǎng)——每日最新資訊28at.com

現(xiàn)在,讓我們?yōu)?nbsp;Track 實(shí)體添加缺失的關(guān)系,并刪除 artistName 和 json 屬性:Lxr28資訊網(wǎng)——每日最新資訊28at.com

Lxr28資訊網(wǎng)——每日最新資訊28at.com

并更新 NSManagedObject 子類(lèi)以反映更改,Track.swift 文件代碼如下:Lxr28資訊網(wǎng)——每日最新資訊28at.com

import Foundationimport CoreData@objc(Track)public class Track: NSManagedObject, Identifiable {    @nonobjc public class func fetchRequest() -> NSFetchRequest<Track> {        return NSFetchRequest<Track>(entityName: "Track")    }    @NSManaged public var imageURL: String?    @NSManaged public var lastPlayedAt: Date?    @NSManaged public var title: String?    @NSManaged public var artists: NSSet?    @objc(addArtistsObject:)    @NSManaged public func addToArtists(_ value: Artist)    @objc(removeArtistsObject:)    @NSManaged public func removeFromArtists(_ value: Artist)    @objc(addArtists:)    @NSManaged public func addToArtists(_ values: NSSet)    @objc(removeArtists:)    @NSManaged public func removeFromArtists(_ values: NSSet)}

最后但并非最不重要的,讓我們將新的模型設(shè)置為 .xcdatamodeld 文件的當(dāng)前模型:Lxr28資訊網(wǎng)——每日最新資訊28at.com

Lxr28資訊網(wǎng)——每日最新資訊28at.com

創(chuàng)建映射模型

由于我們告訴 Core Data 不要自動(dòng)推斷映射模型,所以我們將不得不創(chuàng)建一個(gè)映射模型文件來(lái)在兩個(gè)版本之間建立橋梁。Lxr28資訊網(wǎng)——每日最新資訊28at.com

從菜單欄中選擇 File > New > File...,然后選擇 Mapping Model。Lxr28資訊網(wǎng)——每日最新資訊28at.com

Lxr28資訊網(wǎng)——每日最新資訊28at.com

然后,選擇源模型:Lxr28資訊網(wǎng)——每日最新資訊28at.com

Lxr28資訊網(wǎng)——每日最新資訊28at.com

最后,選擇目標(biāo)模型:Lxr28資訊網(wǎng)——每日最新資訊28at.com

Lxr28資訊網(wǎng)——每日最新資訊28at.com

編寫(xiě)自定義遷移策略

默認(rèn)情況下,Core Data 將盡力映射屬性,并且大部分工作都將由它自動(dòng)完成(包括已刪除的屬性)。Lxr28資訊網(wǎng)——每日最新資訊28at.com

然而,由于我們創(chuàng)建了一個(gè)新的實(shí)體,并且我們希望保留現(xiàn)有數(shù)據(jù),因此我們需要告訴 Core Data 如何遷移。Lxr28資訊網(wǎng)——每日最新資訊28at.com

我們將創(chuàng)建一個(gè)新的類(lèi),該類(lèi)繼承自 NSEntityMigrationPolicy,并在舊的 Track 實(shí)體上創(chuàng)建并鏈接一個(gè)新的關(guān)系到 Artist 實(shí)體,V2MigrationPolicy.swift 文件代碼如下:Lxr28資訊網(wǎng)——每日最新資訊28at.com

Copy codeimport CoreDatastruct Song: Decodable {    let artists: [Artist]    struct Artist: Decodable {        let id: String        let name: String        let imageURL: String    }}class V2MigrationPolicy: NSEntityMigrationPolicy {    private let decoder = JSONDecoder()    override func createDestinationInstances(forSource sInstance: NSManagedObject, in mapping: NSEntityMapping, manager: NSMigrationManager) throws {        // 1        let sourceKeys = sInstance.entity.attributesByName.keys        let sourceValues = sInstance.dictionaryWithValues(forKeys: sourceKeys.map { $0 as String })        // 2        let destinationInstance = NSEntityDescription.insertNewObject(forEntityName: mapping.destinationEntityName!, into: manager.destinationContext)        let destinationKeys = destinationInstance.entity.attributesByName.keys.map { $0 as String }        // 3        for key in destinationKeys {            if let value = sourceValues[key] {                destinationInstance.setValue(value, forKey: key)            }        }        if let jsonString = sInstance.value(forKey: "json") as? String {            // 3            let jsonData = Data(jsonString.utf8)            let object = try? decoder.decode(Song.self, from: jsonData)            // 4            let artists: [NSManagedObject] = object?.artists.map { jsonArtist in                // 5                let request = Artist.fetchRequest()                request.fetchLimit = 1                request.predicate = NSPredicate(format: "name == %@", jsonArtist.name)                // Do not add duplicates to the list...                if let matchedArtists = try? manager.destinationContext.fetch(request), let matchedArtist = matchedArtists.first {                    return matchedArtist                }                // 6                let artist = NSEntityDescription.insertNewObject(forEntityName: "Artist", into: manager.destinationContext)                artist.setValue(jsonArtist.name, forKey: "name")                artist.setValue(jsonArtist.imageURL, forKey: "imageURL")                artist.setValue(jsonArtist.id, forKey: "id")                return artist            } ?? []            // 7            destinationInstance.setValue(Set<NSManagedObject>(artists), forKey: "artists")        }        // 8        manager.associate(sourceInstance: sInstance, withDestinationInstance: destinationInstance, for: mapping)    }}

讓我們逐步解釋上面的代碼:Lxr28資訊網(wǎng)——每日最新資訊28at.com

  • 獲取源實(shí)體的屬性名稱和值。
  • 創(chuàng)建與源實(shí)體相同類(lèi)型的全新目標(biāo)實(shí)體。
  • 將源實(shí)體的屬性值復(fù)制到目標(biāo)實(shí)體。
  • 如果源實(shí)體具有 json 屬性,則將其解析為 Song 對(duì)象。
  • 為避免重復(fù)項(xiàng),請(qǐng)檢查藝術(shù)家是否已經(jīng)存在于目標(biāo)上下文中。
  • 如果藝術(shù)家不存在,則創(chuàng)建一個(gè)新的 Artist 實(shí)體,將其插入到上下文中,并設(shè)置其屬性。
  • 設(shè)置目標(biāo)實(shí)體上的新藝術(shù)家關(guān)系。
  • 將源和目標(biāo)實(shí)例關(guān)聯(lián)起來(lái)。

最后,讓我們將此自定義策略添加到映射模型中:Lxr28資訊網(wǎng)——每日最新資訊28at.com

Lxr28資訊網(wǎng)——每日最新資訊28at.com

現(xiàn)在,如果我們?cè)俅芜\(yùn)行應(yīng)用程序并使用 Core Data Lab 檢查數(shù)據(jù)庫(kù),我們可以看到一個(gè)新的實(shí)體已經(jīng)填充了正確的數(shù)據(jù)。Lxr28資訊網(wǎng)——每日最新資訊28at.com

總結(jié)

文章介紹了在應(yīng)用程序發(fā)展過(guò)程中,數(shù)據(jù)模型可能需要進(jìn)行更改的情況下,如何使用 Core Data 遷移來(lái)保持?jǐn)?shù)據(jù)的一致性和完整性。首先,它解釋了什么是 Core Data 遷移,以及為什么需要進(jìn)行遷移。接著,通過(guò)一個(gè)示例應(yīng)用程序,詳細(xì)介紹了如何更新數(shù)據(jù)模型,添加新實(shí)體和關(guān)系,以解決現(xiàn)有模型的可擴(kuò)展性問(wèn)題。然后,文章介紹了如何創(chuàng)建映射模型來(lái)定義不同模型版本之間的映射關(guān)系,并演示了如何編寫(xiě)自定義遷移策略來(lái)處理特定情況,例如將舊模型數(shù)據(jù)遷移到新模型的新關(guān)系中。最后,通過(guò)將自定義遷移策略添加到映射模型中,完成了整個(gè)遷移過(guò)程。Lxr28資訊網(wǎng)——每日最新資訊28at.com

本文鏈接:http://www.tebozhan.com/showinfo-26-88935-0.htmlSwift 定制 Core Data 遷移

聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com

上一篇: 誰(shuí)說(shuō)PHP不能異步和并行運(yùn)行?

下一篇: 如何使用 SwiftUI 構(gòu)建 visionOS 應(yīng)用

標(biāo)簽:
  • 熱門(mén)焦點(diǎn)
Top