日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當前位置:首頁 > 科技  > 軟件

Swift 定制 Core Data 遷移

來源: 責編: 時間:2024-05-17 17:48:49 250觀看
導讀前言隨著應用程序和用戶群的增長,你需要添加新功能,刪除其他功能,并改變應用程序的工作方式。這是軟件開發生命周期的自然結果,我們應該接受。隨著應用程序的發展,你的數據模型也會發生變化。你需要更改數據結構的方式,以適

jr428資訊網——每日最新資訊28at.com

前言

隨著應用程序和用戶群的增長,你需要添加新功能,刪除其他功能,并改變應用程序的工作方式。這是軟件開發生命周期的自然結果,我們應該接受。jr428資訊網——每日最新資訊28at.com

隨著應用程序的發展,你的數據模型也會發生變化。你需要更改數據結構的方式,以適應新功能,同時確保用戶不會在不同版本之間丟失任何數據。如果你使用 Core Data 在應用程序中持久化信息,那么 Core Data 遷移就會發揮作用。jr428資訊網——每日最新資訊28at.com

什么是 Core Data 遷移?

Core Data 遷移是將數據模型從一個版本更新到另一個版本的過程,因為數據的形狀發生了變化(例如,添加或刪除新屬性)。jr428資訊網——每日最新資訊28at.com

在大多數情況下,Core Data 將自動處理遷移過程。但是,有些情況下,你需要通過提供一個映射模型來自定義遷移過程,告訴 Core Data 究竟如何從源模型遷移到目標模型中的每個屬性和實體。jr428資訊網——每日最新資訊28at.com

甚至有些情況下,映射模型是不夠的,你需要編寫自定義遷移策略來處理特定情況。這是本文要重點討論的情況。jr428資訊網——每日最新資訊28at.com

示例

讓我們考慮一個應用程序,在 Core Data 棧中存儲表示音樂曲目的對象。模型非常簡單,只包含一個實體:Track,Track.swift 代碼如下:jr428資訊網——每日最新資訊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 實體有五個屬性:jr428資訊網——每日最新資訊28at.com

  • imageURL:表示曲目封面圖像的 URL 的字符串。
  • json:表示來自服務器的原始 JSON 數據響應的字符串。
  • lastPlayedAt:表示上次播放曲目的日期。
  • title:表示曲目的標題的字符串。
  • artistName:表示藝術家的名稱的字符串。

Core Data 棧不會與 iCloud 同步,并具有以下設置,CoreDataStack.swift 文件代碼如下:jr428資訊網——每日最新資訊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)")            }        })    }}

如果你仔細觀察上面的示例,你會注意到我們告訴 Core Data 自動遷移存儲,因為我們不想做漸進式遷移,這種遷移速度慢得多且更復雜,并且我們還告訴 Core Data 不要自動推斷映射模型,這意味著我們將不得不為每個遷移提供一個映射模型文件,并且可以允許我們自定義這個過程。jr428資訊網——每日最新資訊28at.com

持久化了一首歌曲后,使用 Core Data Lab 檢查數據庫,我們可以看到屬性被相應保存:jr428資訊網——每日最新資訊28at.com

jr428資訊網——每日最新資訊28at.com

更新模型

當前版本的模型存在一些可擴展性問題:jr428資訊網——每日最新資訊28at.com

  • 模型僅允許每個曲目有一個藝術家,而實際上,一個曲目可以有多個藝術家。
  • 模型存儲一個表示曲目數據的原始 JSON 字符串,這不太高效,當應用程序需要解析 JSON 字符串以顯示曲目數據以獲取藝術家列表時,可能會導致性能問題。

為了解決這些問題,讓我們刪除 artistName 和 json 屬性,采用一個新的 Artist 實體,該實體將與 Track 實體建立一對多的關系。jr428資訊網——每日最新資訊28at.com

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

創建一個新的模型版本

首先,讓我們通過選擇 .xcdatamodeld 文件,然后從菜單欄中選擇 Editor > Add Model Version... 來創建一個新的模型版本。jr428資訊網——每日最新資訊28at.com

jr428資訊網——每日最新資訊28at.com

給它起一個名稱,并以第一個模型版本為基礎:jr428資訊網——每日最新資訊28at.com

jr428資訊網——每日最新資訊28at.com

現在,讓我們創建 Artist 實體并添加所有字段:jr428資訊網——每日最新資訊28at.com

jr428資訊網——每日最新資訊28at.com

也讓我們為新的 Artist 實體創建 NSManagedObject 子類,Artist.swift 代碼如下:jr428資訊網——每日最新資訊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 實體添加一個對多的 artists 關系,還將向 Artist 實體添加一個對多的 tracks 關系。jr428資訊網——每日最新資訊28at.com

現在,讓我們為 Track 實體添加缺失的關系,并刪除 artistName 和 json 屬性:jr428資訊網——每日最新資訊28at.com

jr428資訊網——每日最新資訊28at.com

并更新 NSManagedObject 子類以反映更改,Track.swift 文件代碼如下:jr428資訊網——每日最新資訊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)}

最后但并非最不重要的,讓我們將新的模型設置為 .xcdatamodeld 文件的當前模型:jr428資訊網——每日最新資訊28at.com

jr428資訊網——每日最新資訊28at.com

創建映射模型

由于我們告訴 Core Data 不要自動推斷映射模型,所以我們將不得不創建一個映射模型文件來在兩個版本之間建立橋梁。jr428資訊網——每日最新資訊28at.com

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

jr428資訊網——每日最新資訊28at.com

然后,選擇源模型:jr428資訊網——每日最新資訊28at.com

jr428資訊網——每日最新資訊28at.com

最后,選擇目標模型:jr428資訊網——每日最新資訊28at.com

jr428資訊網——每日最新資訊28at.com

編寫自定義遷移策略

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

然而,由于我們創建了一個新的實體,并且我們希望保留現有數據,因此我們需要告訴 Core Data 如何遷移。jr428資訊網——每日最新資訊28at.com

我們將創建一個新的類,該類繼承自 NSEntityMigrationPolicy,并在舊的 Track 實體上創建并鏈接一個新的關系到 Artist 實體,V2MigrationPolicy.swift 文件代碼如下:jr428資訊網——每日最新資訊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)    }}

讓我們逐步解釋上面的代碼:jr428資訊網——每日最新資訊28at.com

  • 獲取源實體的屬性名稱和值。
  • 創建與源實體相同類型的全新目標實體。
  • 將源實體的屬性值復制到目標實體。
  • 如果源實體具有 json 屬性,則將其解析為 Song 對象。
  • 為避免重復項,請檢查藝術家是否已經存在于目標上下文中。
  • 如果藝術家不存在,則創建一個新的 Artist 實體,將其插入到上下文中,并設置其屬性。
  • 設置目標實體上的新藝術家關系。
  • 將源和目標實例關聯起來。

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

jr428資訊網——每日最新資訊28at.com

現在,如果我們再次運行應用程序并使用 Core Data Lab 檢查數據庫,我們可以看到一個新的實體已經填充了正確的數據。jr428資訊網——每日最新資訊28at.com

總結

文章介紹了在應用程序發展過程中,數據模型可能需要進行更改的情況下,如何使用 Core Data 遷移來保持數據的一致性和完整性。首先,它解釋了什么是 Core Data 遷移,以及為什么需要進行遷移。接著,通過一個示例應用程序,詳細介紹了如何更新數據模型,添加新實體和關系,以解決現有模型的可擴展性問題。然后,文章介紹了如何創建映射模型來定義不同模型版本之間的映射關系,并演示了如何編寫自定義遷移策略來處理特定情況,例如將舊模型數據遷移到新模型的新關系中。最后,通過將自定義遷移策略添加到映射模型中,完成了整個遷移過程。jr428資訊網——每日最新資訊28at.com

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

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 誰說PHP不能異步和并行運行?

下一篇: 如何使用 SwiftUI 構建 visionOS 應用

標簽:
  • 熱門焦點
Top 日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不
欧美综合国产| 一本久道久久综合中文字幕| 国产精品一区一区三区| 国产欧美日韩中文字幕在线| 国产视频在线观看一区二区三区| 国产一区二区三区免费观看| 亚洲国产精品女人久久久| 99精品国产99久久久久久福利| 亚洲已满18点击进入久久| 欧美在线1区| 欧美成人久久| 国产精品久久亚洲7777| 韩国一区二区三区在线观看| 91久久综合| 亚洲综合社区| 裸体女人亚洲精品一区| 欧美日韩理论| 国产一区二区三区高清在线观看| 亚洲二区在线观看| 亚洲午夜精品网| 久久免费国产精品1| 欧美日韩在线免费视频| 国产主播在线一区| 一区二区三区四区五区精品视频| 欧美在线免费播放| 欧美日本三区| 狠狠色丁香婷婷综合| 夜夜嗨av一区二区三区网页| 久久精品99无色码中文字幕| 欧美日韩国产另类不卡| 国产一区二区主播在线| 日韩视频一区二区| 久久婷婷久久| 国产精品在线看| 日韩午夜在线电影| 久久久久欧美精品| 国产精品久久久久久久久久免费看| 一区精品在线| 欧美一区二区三区免费视频 | 欧美不卡视频| 国产日韩欧美电影在线观看| 日韩一级在线| 狂野欧美激情性xxxx欧美| 国产精品一区二区你懂得| 亚洲精品视频免费观看| 久久久蜜桃精品| 国产区亚洲区欧美区| 亚洲午夜精品在线| 欧美激情四色| 亚洲第一综合天堂另类专| 欧美一区二区视频观看视频| 欧美视频免费在线| 亚洲麻豆视频| 欧美成人资源| 在线观看三级视频欧美| 欧美中在线观看| 国产精品一区二区在线观看网站 | 蜜桃伊人久久| 国模叶桐国产精品一区| 亚洲欧美激情视频| 欧美天堂在线观看| 日韩亚洲欧美成人一区| 欧美成人一区二免费视频软件| 国产一区二区三区久久精品| 香蕉乱码成人久久天堂爱免费| 欧美午夜视频网站| 99视频一区二区| 欧美精品免费观看二区| 欧美区国产区| 亚洲日本理论电影| 欧美一级夜夜爽| 好吊妞这里只有精品| 久久久不卡网国产精品一区| 亚洲国产精品久久久久秋霞影院 | 欧美激情中文字幕乱码免费| 欧美日韩精品一区| 亚洲黄色免费| 欧美大片免费观看| 亚洲二区免费| 农夫在线精品视频免费观看| 亚洲电影一级黄| 麻豆亚洲精品| 亚洲国产视频a| 欧美激情亚洲自拍| 日韩午夜视频在线观看| 欧美日韩麻豆| 亚洲桃花岛网站| 国产精品―色哟哟| 亚洲免费影视| 国产视频久久| 久久午夜国产精品| 一区国产精品| 国产色视频一区| 午夜久久久久久| 国产精品日韩精品| 久久国产加勒比精品无码| 欧美日韩国产综合网| 欧美人在线视频| 国产美女精品视频| 欧美一区二区高清| 国产一区二区高清不卡| 久久久久久久999| 在线观看日韩欧美| 欧美精品在线观看一区二区| 亚洲另类视频| 国产精品va在线播放我和闺蜜| 亚洲一区二区成人在线观看| 国产精品一区久久久久| 久久精品国产第一区二区三区| 在线观看日韩国产| 欧美极品在线视频| 亚洲一区日韩| 国产综合久久久久久鬼色| 噜噜噜在线观看免费视频日韩| 99精品视频免费观看视频| 国产精品每日更新| 久久久久免费视频| 99精品热视频只有精品10| 国产精品系列在线播放| 久久午夜精品| 在线亚洲精品| 国产一区二区精品| 一区二区三区在线视频免费观看| 亚洲一区二区三区四区五区黄| 欧美交受高潮1| 亚洲欧美久久久| 精品不卡一区| 欧美日韩黄色大片| 香蕉久久夜色精品国产| 亚洲福利专区| 国产精品久久久久永久免费观看| 久久精品欧美日韩| 999亚洲国产精| 国产午夜精品在线| 欧美日本精品一区二区三区| 小嫩嫩精品导航| 亚洲人成人一区二区三区| 国产乱子伦一区二区三区国色天香| 久久综合久久综合这里只有精品| 夜夜嗨av色一区二区不卡| 国产亚洲一本大道中文在线| 欧美黑人多人双交| 欧美一区二区三区四区夜夜大片| 亚洲欧洲精品一区二区精品久久久| 国产精品色在线| 欧美高清不卡在线| 欧美在线视频免费| 一区二区三区久久网| 一区二区三区在线免费视频| 国产精品久久久久久久久果冻传媒 | 欧美一级视频一区二区| 亚洲看片免费| 激情欧美一区二区三区| 国产精品wwwwww| 欧美gay视频| 久久国产黑丝| 亚洲一区二三| 日韩午夜免费视频| 影音先锋成人资源站| 国产精品尤物福利片在线观看| 欧美日本一道本在线视频| 久久综合99re88久久爱| 亚洲欧美影院| 久久久综合网| 亚洲综合电影| 亚洲精品资源| 亚洲成在线观看| 国产一区二区三区久久久| 国产精品久久久久av| 欧美日本二区| 欧美国产日韩一二三区| 久久天天综合| 欧美亚洲综合网| 亚洲综合日韩| 亚洲私人影院| 99这里有精品| 亚洲精品美女在线观看| 在线精品视频一区二区三四| 国产永久精品大片wwwapp| 国产精品欧美一区二区三区奶水| 欧美日本中文字幕| 欧美激情亚洲精品| 欧美成人高清| 模特精品裸拍一区| 久久婷婷国产麻豆91天堂| 欧美在线亚洲综合一区| 亚洲欧美日韩精品| 亚洲一级一区| 亚洲一区二区三区在线播放| 一本色道久久| 一本久久精品一区二区| 99在线精品视频在线观看| 夜夜嗨av一区二区三区四季av| 亚洲三级毛片| 亚洲精品之草原avav久久| 亚洲另类视频| 一二三区精品| 亚洲视频狠狠| 亚洲欧美日韩国产成人精品影院| 亚洲一区影院| 亚洲欧美中文另类| 性伦欧美刺激片在线观看| 午夜视频在线观看一区| 欧美一区影院|