我不知道如何处理发生在我身上的问题。
我有一个使用AFNetworking
从服务器获取JSON
的应用,我使用SQLite
将Core Data
放入NSArray
。但每次我启动一个应用程序时,我必须chceck服务器上是否有一些新对象,并将它们与设备上的本地对象同步。 如何处理服务器和应用之间的同步?
一种方法是清除整个数据库并再次下载所有内容,但我有一个属性保持对象的状态(选择),我不能丢失这些信息。我得到了一个建议,将响应与当前数据库同步,但我真的不知道如何有效地以聪明的方式做到这一点。
我唯一的想法是获取所有内容,并将响应中的每个对象与整个[[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];
这个小家伙拿走一切:
{{1}}
我很感激任何建议......我坚持这个......
答案 0 :(得分: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)复杂性
答案 1 :(得分:0)
您在获取当前数据然后与新数据进行比较时处于正确的位置。 最简单的方法是循环内部的循环:
-(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]);
}
}
答案 2 :(得分:0)
如果您的主要目标是减少净传输和更快的同步,我建议您将服务器更改为版本化数据结构,当用户从服务器加载数据时,您首先上传您设备上的版本号,然后服务器将最新版本与设备上的版本进行比较,确定设备上已有的数据是否已更改,设备上缺少哪些数据,仅将这些数据传输到设备,如果大多数数据保持不变,它将使您的同步更快设备和服务器之间相同。