CoreDataでSQLiteストアの軽量移行を実行しようとしています。 Xcode4.3.1を使用したLion10.7.3での作業。
NSPersistentDocumentサブクラス(AccountDocument)で、永続ストアコーディネーターを構成するために使用されるメソッドをオーバーライドして、移行に適切なオプションを取得できるようにしました。
- (BOOL)configurePersistentStoreCoordinatorForURL:(NSURL *)url ofType:(NSString *)fileType modelConfiguration:(NSString *)configuration storeOptions:(NSDictionary *)storeOptions error:(NSError **)error
{
NSMutableDictionary *newStoreOptions;
if (storeOptions == nil) {
newStoreOptions = [NSMutableDictionary dictionary];
}
else {
newStoreOptions = [storeOptions mutableCopy];
}
[newStoreOptions setObject:[NSNumber numberWithBool:YES] forKey:NSMigratePersistentStoresAutomaticallyOption];
[newStoreOptions setObject:[NSNumber numberWithBool:YES] forKey:NSInferMappingModelAutomaticallyOption];
BOOL result = [super configurePersistentStoreCoordinatorForURL:url ofType:fileType modelConfiguration:configuration storeOptions:newStoreOptions error:error];
return result;
}
(そのヒントをくれたMalcolm Crawfordに感謝します:http://homepage.mac.com/mmalc/CocoaExamples/controllers.html)
アプリを実行すると、NSPersistentDocumentの実装で失敗します-managedObjectModel
:
* thread #1: tid = 0x2703, 0x00007fff931d9350 libobjc.A.dylib`objc_msgSend_vtable13 + 16, stop reason = EXC_BAD_ACCESS (code=13, address=0x0)
frame #0: 0x00007fff931d9350 libobjc.A.dylib`objc_msgSend_vtable13 + 16
frame #1: 0x00007fff8935e975 CoreData`-[NSKnownKeysDictionary1 _setValues:retain:] + 197
frame #2: 0x00007fff8935f288 CoreData`_newReadModelFromBytes + 648
frame #3: 0x00007fff8935b93e CoreData`+[NSManagedObjectModel(_NSManagedObjectModelPrivateMethods) _newModelFromOptimizedEncoding:error:] + 9310
frame #4: 0x00007fff89359451 CoreData`-[NSManagedObjectModel(_NSManagedObjectModelPrivateMethods) initWithContentsOfOptimizedURL:] + 305
frame #5: 0x00007fff89358d7b CoreData`-[NSManagedObjectModel initWithContentsOfURL:] + 443
frame #6: 0x00007fff893e9519 CoreData`+[NSManagedObjectModel mergedModelFromBundles:] + 377
frame #7: 0x00007fff8ded7037 AppKit`-[NSPersistentDocument managedObjectModel] + 301
frame #8: 0x00007fff8ded70b3 AppKit`-[NSPersistentDocument managedObjectContext] + 75
frame #9: 0x00007fff8ded6e3f AppKit`-[NSPersistentDocument _persistentStoreCoordinator] + 18
frame #10: 0x00007fff8ded6b5d AppKit`-[NSPersistentDocument configurePersistentStoreCoordinatorForURL:ofType:modelConfiguration:storeOptions:error:] + 51
frame #11: 0x0000000100003193 BeanCounter`-[AccountDocument configurePersistentStoreCoordinatorForURL:ofType:modelConfiguration:storeOptions:error:] + 419 at AccountDocument.m:298
ドキュメントからわかることから、デフォルトの実装は次のようになります。
- (id)managedObjectModel
{
NSManagedObjectModel *result = [NSManagedObjectModel mergedModelFromBundles:nil];
return result;
}
したがって、問題をもう少しデバッグするために、次の方法でそのメソッドをオーバーライドします。
- (id)managedObjectModel
{
NSBundle *bundle = [NSBundle mainBundle];
NSURL *url = [bundle URLForResource:@"AccountDocument2" withExtension:@"momd"];
NSManagedObjectModel *result = [[[NSManagedObjectModel alloc] initWithContentsOfURL:url] autorelease];
return result;
}
(アイデアをくれたJeff LaMarcheに感謝します:http://iphonedevelopment.blogspot.com/2009/09/core-data-migration-problems.html)
バンドルとURLはどちらも、私が期待する場所を指しています(そして、Marcus Zarraのアドバイスに従ってプロジェクトをクリーンアップしたので、アプリケーションパッケージに.momまたは.momdのバンドルが含まれていません。mergedModelFromBundlesの使用:およびバージョン管理(CoreData))。それでも、URLからモデルをロードしている間、アプリはクラッシュし続けます。
AccountDocument2.xcdatamodeldが、バージョン管理用の2つのモデル(AccountDocument 2.xcdatamodelと(元の)AccountDocument.xcdatamodel)を持つパッケージであることを確認しました。ファイルプロパティの「バージョン管理されたコアデータモデル」ポップアップメニューが「AccountDocument2」に設定されています。
2つのモデルの唯一の違いは、1つのエンティティに追加の(およびオプションの)属性があることです。私の理解では、軽量移行のモデルを認定します。
明らかに、私はここで何か間違ったことをしていますが、何が起こっているのかわかりません。どんな助けでも大歓迎です…
更新:
Martinの提案(およびNSPersistentDocumentドキュメントのチェック)に従って、アクセサーに次のコードを使用してみました。
- (id)managedObjectModel
{
static id sharedManagedObjectModel = nil;
if (sharedManagedObjectModel == nil) {
NSBundle *bundle = [NSBundle mainBundle];
NSURL *url = [bundle URLForResource:@"AccountDocument2" withExtension:@"momd"];
sharedManagedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:url];
}
return sharedManagedObjectModel;
}
まだクラッシュしています…
更新
Twitterでいくつか提案した後、Xcode 4.3.2にアップグレードしましたが、問題は解決しません。
レイジアップデート
SnowLeopardでXcode4.2を使用して、バージョン管理されたモデルパッケージ(AccountDocument2.xcdatamodeld)を作成しました。アプリをビルドして実行すると、すべてが期待どおりに機能します。
次に、AccountDocument2.xcdatamodeldファイルパッケージをLionとXcode4.3.2に戻しました。アプリをビルドして実行すると、.momdリソースの読み込み中にクラッシュし続けます。はい、子供たち、つまりXcode 4.3.xとデータモデルコンパイラ(MOMC)のせいです。 SnowLeopardですべてのビルドを実行する以外の回避策はありません。
私はXcode4をbashする人ではありませんが、ツールチェーンが不透明な仕様(.xcdatamodelと.xcdatamodeld)から不透明なファイル(.momと.momd)を生成できない状況に陥った場合、それを行うのはかなり困難です。 MacおよびiOSツールの状態について明るいこと。これらのプラットフォームのコアコンポーネントが壊れて、最新バージョンのSDKと開発者ツールでアプリをビルドして実行できないのはばかげています。
このアップデートに来ました
これがXcode4.3.2のデータモデルコンパイラ(MOMC)の重大なバグであることのより多くの証拠:Xcode 4.2によって作成されたリソースフォルダからプロジェクトに.momdバンドルをコピーし、それらをコピーファイルとしてビルドに追加した場合ビルドフェーズでは、アプリケーションは正常に動作します。
また、さまざまなエンティティの属性の検証ルールとデフォルト値を削除するテストもいくつか行いました(以下のマーカスの提案に基づいています)。変更はありませんが、コンパイラは引き続き無効な.momdを作成します。また、何も変更されていないバージョン管理されたモデルを作成しようとしました。コンパイルされた.momdが引き続きクラッシュしました。したがって、現在のモデル(およびそれらが表すデータ)にあるものはすべて、問題の原因です。
また、このバグはNSPersistentDocumentに限定されていません(この質問を始めたときに最初に考えたように)。使用するだけでアプリがクラッシュする可能性があります。[[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]
.
今のところ、SnowLeopardのXcode4.2を使用してモデルを編集/バージョン管理し、コンパイルされたリソースをLionのXcode4.3.2に移動します。 Core Dataを何らかの方法で使用する場合は、このバグが解決されるまで同じことを行うことをお勧めします。私を信じてください、あなたがそうしなければ、あなたは何が起こっているのかを理解しようと何日も費やすでしょう。
レーダーを送信します…
レーダーの更新
私はこのレーダーを提出しました:
http://www.openradar.me/11184500
Oh Crap It Must Be Lion Update
Xcode 4.2 forLionツールをからダウンロードしてインストールしましたhttp://developer.apple.com/downloads。レーダーで使用されているサンプルアプリケーションはまだクラッシュします。
(注:DeveloperTools.pkgの署名に使用された証明書の有効期限が切れているため、Xcode 4.2.1をインストールできません。Xcode4.2のみが機能します。)
NDAを利用している場合は、ベータツールも役に立たないことがわかります。
Xcode4.2がインストールされたSnowLeopardのコピーがあることを願っています。http://furbo.org/2012/03/28/vmware-for-developers/
WTF Do Fetchリクエストは、バージョン管理されたエンティティと属性の更新と関係があります
TwitterのEvadneWu経由:
https://twitter.com/#!/evadne/status/187625192342818818
そして彼女がそれをどのようにしたか:
https://twitter.com/#!/evadne/status/187629091518816258
(.momファイルはバイナリplistです。)
問題の根本は、単一のフェッチ要求です。それが、あるモデルから別のモデルへのデータの移行にどのように影響するかは、Appleのエンジニアが理解することです。
すべての答え
コンパイルされた.momdリソースは、「existingPartner」フェッチ要求が次の場所から変更された後にロードできます。
に:
データの永続性に影響を与えないオブジェクトモデルの一部がバージョン管理と軽量移行を壊すのは直感に反します。これが当てはまらないことは、ドキュメントから明らかです。
の力を使うチョークロックフェッチリクエストを修正するか、完全に削除して信頼するコードで作成されたNSPredicates.
管理対象オブジェクトモデルをインスタンス変数に格納する必要があると思います。自動解放されたオブジェクトを返していますが、これがアクセス不良の原因である可能性があります。
MOMCの問題であるというあなたの理論に基づいて、お母さんに検証ルールはありますか?
検証ルールが4.xMOMCに耐えられないという報告を見てきました。
これは、iOS5が最初にベータ版でリリースされたときにフェッチリクエストを使用したときに発生した問題に関連している可能性があります。ビルド警告が発生し、起動時にアプリがクラッシュしていました。私は実際にはフェッチ要求を使用していなかったので、それを削除し、すべてが正常に機能しました。Core Data警告:「バージョンハッシュ情報はすべてのモデルで利用できるわけではありません」
Leave a Reply