コアデータモデルの更新ああ.
CoreDataを使用して任意の時間を費やしている場合は、意見があります.
個人的には大好きです.それはグラフィカルなモデリングとの関係の解像度を持つ単純な永続層です.現在
あなたはcoredataが
最もベテラン開発者にも恐怖を打つことができる1つの活動はあなたのアップグレードです
実際には、あなたの永続的なストアにアップグレードトグルを使用して、自動化されたモデルのアップグレードシステムを使用して、ほとんど簡単かつ透明です.
どのように新しいあなたのモデルを更新せずに対処する
あなたは
最初にすることは
自動生成されたクラスファイルか、自分で作成したもののどちらかがこのようになります
次に、合成辞書に簡単にアクセスを提供します.
合成プロパティを実装する方法は
コストは 使用する時間.それぞれの要求は、シャッフルする必要があります CPUサイクル= =消費電力. 経由でアクセスできない 可能な技術負債は最初に正しくそれをしていないから. MacOSのショートテストを受けることができます
アクセスして更新する
追加操作は〜5倍高価です. 更新は〜6倍より高価です. 読むよりも2倍高価です.
多くの状況を読むには、キャッシュを使用することができます.しかし、これはあなたの記憶のフットプリントを増加させます.
その違いを見てみなさい.
属性を合成版にダンプすることによってモデルのアップグレードを避けることができますが、処理コストに関して大きな欠点があります.このテクニックは、パフォーマンスに敏感なループに適していないでしょう.
あなたはこのテクニックで穴から自分を掘ることができるかもしれないが、長期的な拡張戦略としてそれに依存しないでください.新しいモデルの世代を作成します.
個人的には大好きです.それはグラフィカルなモデリングとの関係の解像度を持つ単純な永続層です.現在
NSPersistentContainer
APIは、コードのわずか数行で紡績することができます.それを明らかにそれを作るチームは、毎年、また、改善の新鮮な収穫をもたらします.あなたはcoredataが
SQLite
データベース.デフォルトのモードでは、データをSQLite
単なる実装の詳細です.CoreDataもリレーショナルデータベースではないので、1つのように扱うことはありません.最もベテラン開発者にも恐怖を打つことができる1つの活動はあなたのアップグレードです
xcdatamodel
. プロパティの追加のような単純な変更は非常に簡単ですが、関係を変更するような複雑な変更は難しい場合は特に対処するために複数のモデルのバージョンを持つことができます.誰もクライアントデータを失いたくない.実際には、あなたの永続的なストアにアップグレードトグルを使用して、自動化されたモデルのアップグレードシステムを使用して、ほとんど簡単かつ透明です.
let container = NSPersistentContainer(name: "Unicorn")
let url = //url to store file
let store = NSPersistentStoreDescription(url: url)
store.shouldMigrateStoreAutomatically = true
store.shouldInferMappingModelAutomatically = true
container.persistentStoreDescriptions = [store]
container.loadPersistentStores { (storedesc, error) in
//do data dependant setup
}
あなたは設定できますshouldMigrateStoreAutomatically
& shouldInferMappingModelAutomatically
to true
そして、あなたの時代に進んでください.どのように新しいあなたのモデルを更新せずに対処する
xcdatamodel
バージョン?あなたが事前に準備する場合は、恐ろしいモデルのアップグレードを避けるためにあなたのエンティティに部屋をちらりと少し追加することができます.あなたは
Bucket of Goo
™ テクニック.エンティティ内の場所を追加してジェネリックを格納しますDictionary
とその辞書の合成プロパティを格納します.これはかなりの反パターンではありませんが、技術的な負債の形で直接的なコストがあるので、それは非常にスケーラブルではありません.それでも、それは一時的な穴からあなたを得るかもしれません.最初にすることは
metadata
あなたの属性Entity
活字Data
. また、なぜあなたが使用したくない参照してくださいよString
型として.自動生成されたクラスファイルか、自分で作成したもののどちらかがこのようになります
class Thing: NSManagedObject {
@NSManaged var name: String?
@NSManaged var index: Int16
@NSManaged var metadata1: String?
@NSManaged var metadata2: Data?
}
すべてのプロパティは@NSManaged
オブジェクトCランタイムとKvo力学にそれらをバインドする.次に、合成辞書に簡単にアクセスを提供します.
var metadataDictionaryString: SwiftDict {
get {
let string = metadata1
if let dict = string?.propertyList() as? SwiftDict {
return dict
}
return [:]
}
set {
let string = (newValue as NSDictionary).description
metadata1 = string
}
}
このスニペットを使わないでください.それはあなたが私を過去ばか何を示して含まれていた.それは事実に依拠しているdescription
有効な生成plist
for NSString
, NSDictionary
and NSArray
. thatsもはやそのようなケースとタイプData
実行時にクラッシュします.合成プロパティを実装する方法は
Data
バケットタイプとPropertyListSerialization
往復する.var metadataDictionaryData: SwiftDict {
get {
if let data = metadata2 {
do {
let dict = try PropertyListSerialization.propertyList(from: data, options: [], format: nil) as? SwiftDict
return dict ?? [:]
}
catch {
print("plist decode err - ",error)
}
}
return [:]
}
set {
do {
let data = try PropertyListSerialization.data(fromPropertyList: newValue, format: .binary, options: 0)
metadata2 = data
}
catch {
print("plist encode err - ",error)
}
}
}
次のステップは、新しい予期しない属性を合成することです.レットコールextendedName
.extension Thing {
@objc var extendedName: String? {
get {
return metadataDictionaryData["extendedName"] as? String
}
set {
metadataDictionaryData["extendedName"] = newValue
}
}
}
これで、あなたのモデルに新しい属性がありますxcdatamodel
世代費用はいくらですか。
コストは
Data
ブロブ.NSFetchRequest
, I . E検索できません.アクセスして更新する
name
エンティティのプロパティですThing
.0.00485 s to add 1000 items
0.00513 s to update 1000 items
0.00657 s to read 1000 items
アクセスして更新するextendedName
これはmetadata2
0.02022 s to add extended 1000 items
0.03116 s to update extended 1000 items
0.01254 s to read extended 1000 items
これを軽減できますか。
多くの状況を読むには、キャッシュを使用することができます.しかし、これはあなたの記憶のフットプリントを増加させます.
fileprivate var metadata2Cache: SwiftDict?
var metadataDictionaryData: SwiftDict {
get {
if let cache = metadata2Cache {
return cache
}
if let data = metadata2 {
...
}
return [:]
}
set {
do {
let data = ...
metadata2 = data
metadata2Cache = nil
}
catch {
print("plist encode err - ",error)
}
}
}
キャッシュを最初にロードするget
そして、任意の上でそれを燃やすset
. その違いを見てみなさい.
**0.02022 s to add extended 1000 items
**0.03116 s to update extended 1000 items
**0.01254 s to read extended 1000 items
**0.00972 s to read extended 1000 items
**0.00840 s to read extended 1000 items
最初に読む必要がデコードするData
BLOBが、その後の読み取りはキャッシュから出て、約1.25 xのネイティブ属性よりも高価です.結論
属性を合成版にダンプすることによってモデルのアップグレードを避けることができますが、処理コストに関して大きな欠点があります.このテクニックは、パフォーマンスに敏感なループに適していないでしょう.
あなたはこのテクニックで穴から自分を掘ることができるかもしれないが、長期的な拡張戦略としてそれに依存しないでください.新しいモデルの世代を作成します.
Reference
この問題について(コアデータモデルの更新ああ.), 我々は、より多くの情報をここで見つけました https://dev.to/warrenburton/updating-your-core-data-model-oh-no-2eh0テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol