8

私はアプリケーションを作成しており、CoreDataと対話するためのフレームワークとしてMagicalRecordを使用しています。アプリケーションは、サーバーからポスターの配列をフェッチして、それらを表示します。ポスターはアプリで作成し、ユーザーが必要に応じてサーバーにアップロードすることもできます。

そのため、ユーザーが作成したポスターはCore Dataを使用してローカルデータベースに保存されますが、サーバーから取得したポスターはアプリにのみ表示され、ローカルに保存されないようにする必要があります。同じPosterクラス(現在はNSManagedObjectのサブクラス)を使用して、これらの両方のケースを処理するにはどうすればよいですか?

これが私のクラスです:

@interface Poster : NSObject
@property (nonatomic, retain) NSNumber * posterID;
@property (nonatomic, retain) NSString * artists;
@end

サーバーからposters配列をフェッチするとき、新しいポスターを割り当ててから、属性を割り当てます。

Poster *poster = [[Poster alloc] init];
if ([dict objectForKey:@"id"]) poster.posterID = [dict objectForKey:@"id"];
if ([dict objectForKey:@"artists"]) poster.artists = [dict objectForKey:@"artists"];

しかし、リンクされたposter.posterID = [dictなどに到達すると、アプリケーションはこのエラーでクラッシュします

キャッチされなかった例外'NSInvalidArgumentException'が原因でアプリを終了しています、理由:'-[Poster setPosterID:]:認識されないセレクターがインスタンス0xaa8b160に送信されました'

Poster *poster = [Poster createEntity];の代わりにを使用して新しいオブジェクトを作成するとPoster *poster = [[Poster alloc] init];、アプリはクラッシュしませんが、コンテキストを保存すると、サーバーからフェッチされたすべてのポスターがローカルに保存されていることがわかります。

どうすればこれを解決できますか?

4

2 に答える 2

12

alloc/init管理対象オブジェクトは管理対象オブジェクト コンテキストに関連付ける必要があるため、管理対象オブジェクトだけにすることはできません。poster.posterID = ...動的に作成されたアクセサ メソッドは、管理対象オブジェクト コンテキストがないと機能しないため、クラッシュします。(訂正: @noaが正しく言ったように、指定された初期化子を使用する限り、管理オブジェクトコンテキストなしでオブジェクトを作成できます。ただし、これらのオブジェクトは、フェッチ要求に対して「表示」されません。)

ディスクに保存しない管理対象オブジェクトを作成するには、SQLite ストアと別のインメモリ ストアの 2 つの永続ストアを使用できます。

MagicalRecord でそれを行う方法はわかりませんが、「プレーンな Core Data」では次のように動作します。

管理対象オブジェクト コンテキストと永続コア コーディネーターを作成したら、 2 つの 永続ストアをストア コーディネーターに割り当てます。

NSPersistentStore *sqliteStore, *memStore;

sqliteStore = [coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:nil error:&error];
if (sqliteStore == nil) {
    // ...
}
memStore = [coordinator addPersistentStoreWithType:NSInMemoryStoreType configuration:nil URL:nil options:nil error:&error];
if (memStore == nil) {
    // ...
}

後で新しいオブジェクトをコンテキストに挿入するときに、新しいオブジェクトを SQLite ストアまたはインメモリ ストアに関連付けます。

Poster *poster = [NSEntityDescription insertNewObjectForEntityForName:@"Poster" inManagedObjectContext:context];
[context assignObject:poster toPersistentStore:memStore];
// or: [context assignObject:poster toPersistentStore:sqliteStore];
poster.posterID = ...;
poster.artists = ...;

SQLite ストアに割り当てられたオブジェクトのみがディスクに保存されます。アプリケーションを再起動すると、メモリ内ストアに割り当てられたオブジェクトは失われます。ストアに明示的に割り当てられていないオブジェクトは、最初のストア (この場合は SQLite ストア) に自動的に割り当てられると思います。

私はまだ MagicalRecord を使用していませんが、メソッドMR_addInMemoryStoreMR_addSqliteStoreNamedがあり、この構成に適したメソッドであることがわかります。

于 2012-12-22T17:55:31.457 に答える
3

-initWithEntity:insertIntoManagedObjectContext:2 番目のパラメーターに nil を指定して、指定されたイニシャライザーを使用することもできます。(私の経験では、管理対象オブジェクトの一部の側面は、コンテキストがなくても正常に機能しますが、そうでない側面もあります。)

この回答にはもう少し説明があります。

于 2012-12-22T18:11:07.263 に答える