【问题标题】:Syncing Core Data with server response将核心数据与服务器响应同步
【发布时间】:2014-02-18 22:34:32
【问题描述】:

我不知道如何处理发生在我身上的问题。

我有一个应用程序,它使用AFNetworking 从我使用Core Data 放入SQLite 的服务器获取JSON。但是每次我启动一个应用程序时,我都必须检查服务器上是否有一些新对象并将它们与设备上的本地对象同步。 如何处理服务器和应用之间的这种同步?

一种方法是清除整个数据库并再次下载所有内容,但我有一个属性保持对象的状态(selected),我不能丢失此信息。有人建议我将响应与当前数据库同步,但我真的不知道如何高效且智能地​​做到这一点。

我唯一的想法是获取所有内容,并将响应中的每个对象与整个 NSArray 进行比较。如果匹配则中断循环,如果没有添加对象。

我正在使用这种方法从服务器获取所有内容并将其放入数据库:

[[AFHTTPRequestOperationManager manager] GET:ALL_GROUPS parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
    for (id group in responseObject) {
        Group *groupEntity = [NSEntityDescription insertNewObjectForEntityForName:@"Group" inManagedObjectContext:self.moc];

        groupEntity.name = [group valueForKey:@"name"];
        groupEntity.cashID = [group valueForKey:@"id"];
        groupEntity.caseInsensitiveName = [[group valueForKey:@"name"] lowercaseString];
        groupEntity.selected = FALSE;

        NSError *error;
        if (![self.moc save:&error]) {
            NSLog(@"Couldn't save: %@", [error localizedDescription]);
        }
    }
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    // Show alert with info about internet connection
    UIAlertView *internetAlert = [[UIAlertView alloc] initWithTitle:@"Ups!" message:@"Wygląda na to, że nie masz połączenia z internetem" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
    [internetAlert show];
}];

还有这个小家伙来取所有东西:

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Group" 
                                              inManagedObjectContext:self.moc];
    [fetchRequest setEntity:entity];
    NSError *error;
    NSArray *fetchedObjects = [self.moc executeFetchRequest:fetchRequest error:&error];

我将不胜感激任何建议...我坚持这个...

【问题讨论】:

  • 下载到设备的数据可以被用户修改吗?
  • @CarmeloS,只有selected属性可以。
  • 还有一个AFHTTPNetworking实现的NSIncrementalStore,你也可以看看:github.com/AFNetworking/AFIncrementalStore

标签: ios objective-c core-data afnetworking


【解决方案1】:

虽然@Rich 解决方案是正确的,但它是 O(N*M) 复杂度解决方案。
N 是数据库中的组总数
M 是响应中收到的组数

您的成功代码可能是:

NSMutableDictionary* groups = [NSMutableDictionary new];
NSMutableArray* newIds = [NSMutableArray new];
for (id group in responseObject) {
    Group *groupEntity = [NSEntityDescription insertNewObjectForEntityForName:@"Group" inManagedObjectContext:self.moc];

    groupEntity.name = [group valueForKey:@"name"];
    groupEntity.cashID = [group valueForKey:@"id"];
    groupEntity.caseInsensitiveName = [[group valueForKey:@"name"] lowercaseString];
    groupEntity.selected = NO;
    groups[groupEntity.cashID] = groupEntity;
    [newIds addObject:groupEntity.cashID];
}

NSFetchRequest* r = [NSFetchRequest fetchRequestWithEntityName:@"Group"];
[r setIncludesPendingChanges:NO];
r.predicate = [NSPredicate predicateWithFormat:@"cashID IN %@",newIds];
NSArray *existingGroups = [self.moc executeFetchRequest:r error:&error];

for (Group* g in existingGroups) {
    Group* newGroup = groups[g.cashID];
    g.name = [newGroup valueForKey:@"name"];
    g.cashID = [newGroup valueForKey:@"cashID"];
    g.caseInsensitiveName = [[newGroup valueForKey:@"name"] lowercaseString];
    [self.moc deleteObject:newGroup];
}

// Save any changes
NSError *error;
if (![self.moc save:&error]) {
    NSLog(@"Couldn't save: %@", [error localizedDescription]);
}

O(M) 复杂度

【讨论】:

  • 是的,我只是在给他一个继续前进的想法!不过,请注意,您不需要数组来存储 newIds 和字典来存储新组,您可以使用字典的 allKeys 方法。但更重要的是你的谓词是错误的,它必须是cashID IN %@ :)
  • @Rich,谢谢,我已经更正了谓词。该数组是为了避免再次传递对象(另一个 O(M) 操作)
  • @DanShelly 我的代码有一个问题。当我第一次运行它时,它并没有保存任何东西......可能newGroup 应该被声明为Group*
  • @DanShelly 现在一切正常。 [r setIncludesPendingChanges:NO];不见了:)
【解决方案2】:

您在获取当前数据然后与新数据进行比较时处于正确的位置。 最简单的方法是循环内循环:

-(void)makeRequest
{
    [[AFHTTPRequestOperationManager manager] GET:ALL_GROUPS parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
        [self addNewObjects:responseObject];
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        // Show alert with info about internet connection
        UIAlertView *internetAlert = [[UIAlertView alloc] initWithTitle:@"Ups!" message:@"Wygląda na to, że nie masz połączenia z internetem" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
        [internetAlert show];
    }];
}

-(void)addNewObjects:(NSArray *)groups
{
    // Get the current groups
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Group" inManagedObjectContext:self.moc];
    [fetchRequest setEntity:entity];
    NSError *error;
    NSArray *currentGroups = [self.moc executeFetchRequest:fetchRequest error:&error];

    for (id group in groups) {

        id groupID = [group valueForKey:@"id"];

        Group *currentlySavedGroup = nil;

        // Look for a current object
        for (Group *groupEntity in currentGroups) {
            if ([groupEntity.cashID isEqualTo:groupID]) {
                // We've found a current object so finish looking
                currentlySavedGroup = groupEntity;
                break;
            }
        }

        if (!currentlySavedGroup) {
            // Create a new one
            Group *currentlySavedGroup = [NSEntityDescription insertNewObjectForEntityForName:@"Group" inManagedObjectContext:self.moc];
            currentlySavedGroup.selected = NO;
        }

        // Update regardless of saved or not
        currentlySavedGroup.name = [group valueForKey:@"name"];
        currentlySavedGroup.cashID = [group valueForKey:@"id"];
        currentlySavedGroup.caseInsensitiveName = [[group valueForKey:@"name"] lowercaseString];
    }

    // Save any changes
    NSError *error;
    if (![self.moc save:&error]) {
        NSLog(@"Couldn't save: %@", [error localizedDescription]);
    }
}

【讨论】:

    【解决方案3】:

    如果您的主要目标是减少网络传输和更快的同步,我建议您将服务器更改为版本化数据结构,当用户从服务器加载数据时,您首先上传您设备上的版本号,然后服务器将最新版本与设备上的版本进行比较,确定设备上的哪些数据已更改,设备上缺少哪些数据,仅将这些数据传输到设备,如果大多数数据保持不变,这将使您的同步更快设备和服务器之间相同。

    【讨论】:

      猜你喜欢
      • 2012-04-16
      • 1970-01-01
      • 1970-01-01
      • 2012-08-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-16
      相关资源
      最近更新 更多