问题描述
我正在编写一个应用程序,并使用 MagicalRecord 作为与 Core Data 交互的框架.该应用程序从服务器获取一组海报,然后显示它们.如果用户需要,也可以在应用程序上创建海报,然后上传到服务器.
I'm writing an application and I am using MagicalRecord as a framework for interacting with Core Data. The application fetches an array of posters from a server and then displays them. Posters can also be created on the app and then uploaded to the server if the user requires it.
因此,用户创建的海报使用 Core Data 存储在本地数据库中,而从服务器获取的海报应仅显示在应用程序中,而不能保存在本地.如何使用相同的 Poster 类(现在是 NSManagedObject 的子类)来处理这两种情况?
So posters created by the user are stored in the local db using Core Data, while posters fetched from the server should only be displayed in the app but not saved locally. How can I use the same Poster class (which now is a subclass of NSManagedObject) to handle both these cases?
这是我的课:
@interface Poster : NSObject
@property (nonatomic, retain) NSNumber * posterID;
@property (nonatomic, retain) NSString * artists;
@end
当我从服务器获取海报数组时,我会分配一个新海报,然后分配属性:
When I fetch the posters array from the server I allocate a new poster and then assign attributes:
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 etc etc 时,应用程序会因为这个错误而崩溃
But when reaching the linked poster.posterID = [dict etc etc the application crashes with this error
由于未捕获的异常NSInvalidArgumentException"而终止应用,原因:-[Poster setPosterID:]: 无法识别的选择器发送到实例 0xaa8b160"
如果我使用 Poster *poster = [Poster createEntity];
而不是 Poster *poster = [[Poster alloc] init];
创建新对象,应用程序不会崩溃,但是当我保存上下文时,我发现从服务器获取的所有海报都保存在本地.
If I create the new object with Poster *poster = [Poster createEntity];
instead of Poster *poster = [[Poster alloc] init];
, the app doesn't crash, but when I save the context I find all the posters fetched from the server are saved locally.
我该如何解决这个问题?
How can I solve this?
推荐答案
你不能只alloc/init
一个托管对象,因为托管对象必须与托管对象上下文相关联.poster.posterID = ...
崩溃,因为动态创建的访问器方法在没有托管对象上下文的情况下不起作用.(更正:正如@noa 所说的那样,您可以在没有托管对象上下文的情况下创建对象,只要您使用指定的初始值设定项.但这些对象对于任何提取请求都不会可见".)
You cannot just alloc/init
a managed object, because a managed object must be associated with a managed object context. poster.posterID = ...
crashes because the dynamically created accessor methods do not work without a managed object context. (Correction: As @noa correctly said, you can create objects without a managed object context, as long as you use the designated initializers. But those objects would not be "visible" to any fetch request.)
要创建不应保存到磁盘的托管对象,您可以使用两个持久存储:一个 SQLite 存储和一个单独的内存存储.
To create managed objects that should not be saved to disk you can work with two persistent stores: one SQLite store and a separate in-memory store.
我不能告诉你如何用 MagicalRecord 做到这一点,但使用普通核心数据"它会像这样工作:
I cannot tell you how to do that with MagicalRecord, but with "plain Core Data" it would work like this:
在创建托管对象上下文和持久核心协调器后,您将两个持久存储分配给存储协调器:
After creating the managed object context and the persistent core coordinator, you assign two persistent stores to the store coordinator:
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 存储或内存存储关联:
Later, when you insert new objects to the context, you associate the new object either with the SQLite store or the in-memory store:
Poster *poster = [NSEntityDescription insertNewObjectForEntityForName:@"Poster" inManagedObjectContext:context];
[context assignObject:poster toPersistentStore:memStore];
// or: [context assignObject:poster toPersistentStore:sqliteStore];
poster.posterID = ...;
poster.artists = ...;
只有分配给 SQLite 存储的对象才会保存到磁盘.如果您重新启动应用程序,分配给内存存储的对象将消失.我认为未明确分配给存储的对象会自动分配给第一个存储,在本例中将是 SQLite 存储.
Only the objects assigned to the SQLite store are saved to disk. Objects assigned to the in-memory store will be gone if you restart the application. I think that objects that are not assigned explicitly to a store are automatically assigned to the first store, which would be the SQLite store in this case.
我还没有使用过 MagicalRecord,但我看到有方法 MR_addInMemoryStore
和 MR_addSqliteStoreNamed
,它们将是此配置的合适方法.
I haven't worked with MagicalRecord yet, but I see that there are methods MR_addInMemoryStore
and MR_addSqliteStoreNamed
, which would be the appropriate methods for this configuration.
这篇关于如何使用 Core Data 模型而不保存它们?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!