RESTKit:在覆盖之前,将GET对象与本地持久化 [英] RESTKit: Comparing GET object with locally persisted before overwriting

查看:169
本文介绍了RESTKit:在覆盖之前,将GET对象与本地持久化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个保存的对象(持久)在Core Data。让我们来看下面的值:

  // Entity:employee 
objectID:1111
firstName:@ Jon
lastName:@D
modified:@10:45 PM


$ b b

现在,我做一个 RKManagedObjectRequestOperation *操作请求。



我设置 operation.savesToPersistentStore = NO; 并开始操作。



对象已下载,并已修改为以下内容:

  // Entity:employee 
objectID:1111
firstName:@Jonathan
lastName:@Doe
modified:@10:55 PM
/ /我有15个其他属性,字符串,NSDate,NSNumber和BOOLs

修改的对象在 managedObjectContext



中的时间如果修改上下文中,我想比较每个属性上下文与持久保存在Core Data中的一样。如果 Context 属性不同于持久化的属性,我需要为每个属性属性触发一个标志。一旦所有的属性都被解除,我可以通过保存上下文来覆盖对象。



我想我必须手动检查:

  if(!([objectInCoreData valueForKey:@firstName] isEqualToString:[objectInContext valueForKey @firstName]))
{
firstNameValueChange = YES; //触发此标志
//我必须为每个改变的属性触发一个标志以显示
//以不同的颜色改变tableView中的值
}

//继续检查每个属性,最后覆盖用上下文保存
[self.managedObjectContext save:& error];问题1:我有一种感觉,有一个更好的方法来做到这一点。。

什么是最佳实践?

如何简化检查15个不同属性的代码?



问题2:在哪里测试每个属性是否已更改?里面的successBlock? wilSave:method?



** UPDATE *

  RKManagedObjectRequestOperation * operation = [[RKManagedObjectRequestOperation alloc] initWithRequest:request responseDescriptors:@ [responseDescriptor]]; 
operation.managedObjectContext = self.objectManager.managedObjectStore.mainQueueManagedObjectContext;
operation.managedObjectCache = appDelegate.managedObjectStore.managedObjectCache;
operation.savesToPersistentStore = NO;


[operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation * operation,RKMappingResult * mappingResult){

NSSet * updatedObjects = [self.managedObjectContext updatedObjects];
NSLog(@updatedObjects Count%i,updatedObjects.count);

NSArray * _updatedObjects = updatedObjects.allObjects;
NSLog(@_ updatedObjects Count%i,_updatedObjects.count);

for(int i = 0; i <_updatedObjects.count; i ++)
{
Invite * invite = [_updatedObjects objectAtIndex:i];
NSDictionary * changedValues = [invite changedValues];
}
}失败:^(RKObjectRequestOperation * operation,NSError * error){}

记录

  I restkit.network:RKObjectRequestOperation.m:250 GET'http://www.domain.com/ api?lastrequest = 2014-04-22T07%3A06%3A34Z'(200 OK / 28 objects)[request = 0.1140s mapping = 0.0865s total = 0.3034s] 
2014-04-29 07:06:43.112应用程式[10627:60b] updatedObjects Count 0
2014-04-29 07:06:43.112 App [10627:60b] _updatedObjects Count 0

我可以看到我得到一些对象的日志,但一切都为null或0.我猜我的MOC是空白的。如何对象从 mappingResult MOC

解决方案

下面的选项不能正常工作,因为MOC被保存即使保存不被传播到持久化存储,所以你不能问它的变化。您可以使用相同方法的多个上下文,但是:



RestKit能够使用KVC验证。因此,您可以在模型对象上实现多个方法,并添加验证逻辑。这些方法使用新的传入数据调用,并且可以访问当前数据( self 的实例变量),因此您可以检查传入值,并检查是否要:


  1. 接受

  2. 更改



  3. 请参阅 this ref






    updatedObjects 。一旦你有更新的对象,你可以得到 changedValues 每个。现在,使用该字典中的键,您可以使用 committedValuesForKeys:获得以前保存的值。



    具有进行比较所需的所有信息。你应该处理每个键,并应用任何你想要的逻辑。作为处理的一部分,您可以将一些变量改回其保存的值,或使用 refreshObject:mergeChanges:重置整个对象。

    在处理结束时,保存上下文。



    您不应该使用多个不同的上下文来实现这一点,不同于标准主队列上下文的上下文。


    I have a saved object (persisted) in Core Data. Lets say below are the values:

    //Entity: employee
    objectID: 1111
    firstName: @"Jon"
    lastName: @"D"
    modified: @"10:45PM"
    

    Now, I do a RKManagedObjectRequestOperation *operation request.

    I set operation.savesToPersistentStore = NO; and start the operation.

    The object was downloaded and it's been modified to the following:

    //Entity: employee
    objectID: 1111
    firstName: @"Jonathan"
    lastName: @"Doe"
    modified: @"10:55PM"
    //I have 15 other properties that are either Strings, NSDate, NSNumber, and BOOLs
    

    I believe at this time the modified object is in the managedObjectContext

    If the modified date is different in the Context, I would like to compare each attribute in the Context with the one that's persisted in Core Data. And if the Context attribute is different than the one in persisted, I need to trigger a flag for each attribute property. Once all the attributes have been chacked, I can overwrite the object by saving the Context.

    I'm thinking I'll have to manually check:

    if (!([objectInCoreData valueForKey:@"firstName"] isEqualToString:[objectInContext valueForKey@"firstName"])) 
    { 
         firstNameValueChange = YES; // Trigger this flag
         // I have to trigger a flag for each attribute that's changed to show 
         // the changed value in the tableView in a different color
    }
    
    //Continue to check for each attribute, and at end overwrite persisted with Context by
    [self.managedObjectContext save:&error];
    

    Question 1: I have a feeling there's a better way to do this. What's the best practice?
    How can I simplify the code for checking 15 different attributes?

    Question 2: Where do I test if each attribute has changed? inside the successBlock? wilSave: method?

    ** UPDATE *

    RKManagedObjectRequestOperation *operation = [[RKManagedObjectRequestOperation alloc]initWithRequest:request responseDescriptors:@[responseDescriptor]];
    operation.managedObjectContext = self.objectManager.managedObjectStore.mainQueueManagedObjectContext;
    operation.managedObjectCache = appDelegate.managedObjectStore.managedObjectCache;
    operation.savesToPersistentStore = NO;
    
    
    [operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
    
        NSSet *updatedObjects = [self.managedObjectContext updatedObjects];
        NSLog(@"updatedObjects Count %i", updatedObjects.count);
    
        NSArray *_updatedObjects = updatedObjects.allObjects;
        NSLog(@"_updatedObjects Count %i", _updatedObjects.count);
    
        for (int i = 0; i<_updatedObjects.count; i++)
        {
            Invite *invite = [_updatedObjects objectAtIndex:i];
            NSDictionary *changedValues = [invite changedValues];            
        }
    }failure:^(RKObjectRequestOperation *operation, NSError *error) {}
    

    Log

     I restkit.network:RKObjectRequestOperation.m:250 GET 'http://www.domain.com/api?lastrequest=2014-04-22T07%3A06%3A34Z' (200 OK / 28 objects) [request=0.1140s mapping=0.0865s total=0.3034s]
    2014-04-29 07:06:43.112 App[10627:60b] updatedObjects Count 0
    2014-04-29 07:06:43.112 App[10627:60b] _updatedObjects Count 0
    

    I can see the log that I'm getting a few objects back, but everything is null or 0. I guess my MOC is blank. How do the objects go from mappingResult to MOC?

    解决方案

    The below option doesn't work correctly because the MOC is saved even if the save isn't propagated up to the persistent store so you can't ask it about its changes. You could use multiple contexts with the same approach, but:

    RestKit is able to use KVC validation. As such you can implement a number of methods on your model objects and add your validation logic. These methods are called with the new incoming data and have access to the current data (the instance variables of self) so you can check the incoming value and check if you want to:

    1. accept it
    2. change it
    3. abort the mapping altogether

    See this ref.


    From the MOC you can get updatedObjects. Once you have the updated objects you can get the changedValues for each. Now, using the keys from that dictionary, you can get the previous saved values with committedValuesForKeys:.

    Now you have all the information required to make your comparison. You should process each of the keys and apply whatever logic you want. As part of the processing you can change some variables back to their saved values, or reset the entire object using refreshObject:mergeChanges:.

    At the end of your processing, save the context.

    You should not be using multiple different contexts to achieve this, though you should probably be using a different context from the standard main queue context.

    这篇关于RESTKit:在覆盖之前,将GET对象与本地持久化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆