更新核心数据的最佳做法是什么?
我正在工作的第一个正在工作的人现在在ViewController中创建了所有与Core Data相关的函数,但是我想在模型类(NSManagedObject子类)中声明它们以分离关注点。
主要功能是AFNetworking postPath,它调用Web服务并返回要添加/编辑/删除的对象数组。我所做的是创建一个类方法并在其中执行此AFNetwork调用:
+ (void)updateEbooksListWithSuccessBlock:(void (^)())successBlock andFailureBlock:(void (^)())failureBlock {
NSURL *url = urlSchema (urlWebServices, @"");
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url];
NSString *postPath = [NSString stringWithFormat:@"ws-ebooks-lista.php"];
[httpClient postPath:postPath parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
if ([operation isKindOfClass:[AFHTTPRequestOperation class]]) {
NSDictionary *result = [[responseObject objectFromJSONData] retain];
bool success = statusDoRetornoDoWebService(result); //Function that checks if the return was successful
//Configura o Core Data
NSError *error = nil;
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSManagedObjectContext *localManagedObjectContext = [[NSManagedObjectContext alloc] init];
[localManagedObjectContext setParentContext:[(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext]];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Ebooks" inManagedObjectContext:localManagedObjectContext];
NSPredicate *filterPredicate;
[request setEntity:entity];
if (success) {
NSArray *ebookInfos = [result objectForKey:@"saida"];
Ebooks *ebook;
NSManagedObject *objectInsert;
for (NSDictionary* ebookInfo in ebookInfos) {
filterPredicate = [NSPredicate predicateWithFormat:@"ebooks_id == %@",[ebookInfo valueForKey:@"id_ebook"]];
[request setPredicate:filterPredicate];
ebook = [[localManagedObjectContext executeFetchRequest:request error:&error] lastObject];
objectInsert = [NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:localManagedObjectContext];
if (ebook) {
if (![[ebookInfo valueForKey:@"excluido"] isEmpty]) {
//Delete Ebook
} else {
//Update Ebook
}
} else {
//Add Ebook
}
if (![localManagedObjectContext save:&error]) {
//Log Error
}
[objectInsert release];
}
}
[request release];
[localManagedObjectContext release];
}
[successBlock invoke];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
//Failure
[failureBlock invoke];
}];}
它在应用程序运行时工作正常,但如果我关闭它(通过Xcode)并再次打开它,则不会保存更改。我尝试不使用“父上下文”方式,只使用AppDelegate托管对象上下文(因为AFNetworking回调总是在主队列上运行)但没有成功:数据不会持久化。这是为什么?难道我做错了什么?这是不好的做法吗?我应该按照原样保留View Controller中的所有内容吗?
谢谢!
答案 0 :(得分:3)
我认为将太多与您的数据模型相关的逻辑放入您的实体类中是一个坏主意。这些任务根本不属于那里。实体类应该只关注它们封装的内容:实体实例本身。
举例说明:想象一个代表数字的类(如NSNumber
)。它认为扩展它是不方便的,例如,在一定限度内的所有偶数的数组,或Fibonacci系列的第n个成员。让一个数字类负责将自己保存到文件或从网上检索信息似乎是不合理的。
由于这些和类似的原因,我认为核心数据实体的获取和保存属于控制器,而不是实体类。请记住,MVC(模型 - 视图 - 控制器)模式背后的基本思想之一是控制器操纵模型或询问信息,而不是模型操纵自己。
我推测您的麻烦主要来自于没有充分分离应用程序的各个功能方面(数据模型,持久性,网络操作,用户交互)。
答案 1 :(得分:1)
呃...我要做的是制作非常裸的NSManagedObject
子类...然后用categories扩展它们,这样当你从没有更新的模型中重新生成类时尝试合并所有自定义逻辑。
自定义逻辑也属于模型,模型包含类别或类扩展。
所以从视图控制器中取出废话并将其放在一个易于维护的类别中,如果有必要,可以将其放在几个类别中。