在尝试将网络服务数据与本地商店同步时,我在逻辑中遗漏了一些东西,我需要你的帮助。这就是我所拥有的:
我有一个NSArray
NSDictionaries
描述每个事件对象(从网上下载),我按事件ID排序。然后我使用IN谓词获取本地存储,并按事件ID对其进行排序。然后我尝试迭代并匹配id,如果匹配,我更新记录,如果他们不匹配,我创建新的NSManagedObject
。如果新下载的事件对象的eventID比本地存储中的最后一个eventID更大,则它可以正常工作,但如果来自Web服务的eventID小于本地存储中的eventID,那么 INSERTS ALL OBJECTS ,无论如何如果他们存在或不存在,那确实是我的问题。
所以换句话说,如果新记录位于排序数组的开头,它将添加每个对象,但如果它位于排序数组的末尾,它将更新除新记录之外的所有对象。我需要它来创建新的并更新旧的。
这里有一些代码:
具有逻辑的功能,我相信我错过了一些东西:
- (void)findOrCreateObject:(NSArray*)eventArray
{
NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
//get sorted stored records
NSArray *fetchedRecords = [self.fetchedResultsController fetchedObjects];
//sort dictionaries
NSSortDescriptor *aSortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"id" ascending:YES];
NSArray *downloadedRecords = [self.events sortedArrayUsingDescriptors:[NSArray arrayWithObject:aSortDescriptor]];
NSLog(@"DOWNLOADED EVENTS = %@", downloadedRecords);
NSLog(@"FETCHED EVENTS = %@", fetchedRecords);
//if store is not empty we need to walk through data and add/update records, otherwise/ELSE we need to import initial data
if (fetchedRecords.count != 0) {
//stores has records already
NSLog(@"FIND OR CREATE PROCESS");
if ([downloadedRecords count] > 0) {
NSArray *storedRecords = [self fetchEvents:eventArray withContext:context];
NSUInteger currentIndex = 0;
for (NSDictionary* event in downloadedRecords) {
Event* eventObject = nil;
if ([storedRecords count] > currentIndex) {
eventObject = [storedRecords objectAtIndex:currentIndex];
}
NSLog(@"STRING VALUE OF KEY = %@", [[eventObject valueForKey:@"eventID"]stringValue]);
if ([[event valueForKey:@"id"] isEqualToString:[[eventObject valueForKey:@"eventID"] stringValue]]) {
//Update Record
NSLog(@"Updating Record!!!");
[self updateManagedObject:eventObject withRecord:event inContext:context];
}
else
{
//New Record
NSLog(@"Inserting Record!!!");
eventObject = (Event*)[NSEntityDescription insertNewObjectForEntityForName:@"Event" inManagedObjectContext:context];
eventObject.eventID = [self makeNumberFromString:[event valueForKey:@"id"]];
eventObject.title = [event valueForKey:@"title"];
eventObject.venue = [event valueForKey:@"venue"];
}
currentIndex++;
}
}
}
else
{
//import initial data
NSLog(@"IMPORTING INITIAL DATA");
for (NSDictionary* event in downloadedRecords) {
Event *eventObject = (Event*)[NSEntityDescription insertNewObjectForEntityForName:@"Event" inManagedObjectContext:context];
eventObject.eventID = [self makeNumberFromString:[event valueForKey:@"id"]];
eventObject.title = [event valueForKey:@"title"];
eventObject.venue = [event valueForKey:@"venue"];
}
}
// Save the context.
NSError *error = nil;
if (![context save:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
}
}
FETCHEVENTS 方法:
-(NSArray*)fetchEvents:(NSArray*)eIDs withContext:(NSManagedObjectContext*)context
{
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Event" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(eventID IN %@)", eIDs];
[fetchRequest setPredicate:predicate];
[fetchRequest setSortDescriptors:@[ [[NSSortDescriptor alloc] initWithKey: @"eventID" ascending:YES] ]];
NSError *error = nil;
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
if (fetchedObjects == nil) {
NSLog(@"No rows returned");
}
return fetchedObjects;
}
更新对象方法:
- (void)updateManagedObject:(NSManagedObject*)object withRecord:(NSDictionary*)record inContext:(NSManagedObjectContext*)context
{
[object setValue:[self makeNumberFromString:[record valueForKey:@"id"]] forKey:@"eventID"];
[object setValue:[record valueForKey:@"title"] forKey:@"title"];
[object setValue:[record valueForKey:@"venue"] forKey:@"venue"];
}
下载Web服务数据并解析后,我调用了findOrCreate方法。
如果您有任何其他问题,请告诉我。
答案 0 :(得分:1)
试试这个,
- (void)findOrCreateObject:(NSArray*)eventArray {
//if store is not empty we need to walk through data and add/update records, otherwise/ELSE we need to import initial data
if (fetchedRecords.count != 0) {
//stores has records already
NSLog(@"FIND OR CREATE PROCESS");
if ([downloadedRecords count] > 0) {
NSArray *storedRecords = [self fetchEvents:eventArray withContext:context];
for (NSDictionary* event in downloadedRecords) {
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"eventID = %@",[event valueForKey:@"id"]];
NSArray *matchedArray = [storedRecords filteredArrayUsing
Predicate:predicate];
Event* eventObject = nil;
if ([matchedArray count] > 0) {
//Update Record
NSLog(@"Updating Record!!!");
eventObject = [matchedArray objectAtIndex:0];
[self updateManagedObject:eventObject withRecord:event inContext:context];
}
else
{
//New Record
NSLog(@"Inserting Record!!!");
eventObject = (Event*)[NSEntityDescription insertNewObjectForEntityForName:@"Event" inManagedObjectContext:context];
eventObject.eventID = [self makeNumberFromString:[event valueForKey:@"id"]];
eventObject.title = [event valueForKey:@"title"];
eventObject.venue = [event valueForKey:@"venue"];
}
}
}
} else {
.....
}
}
答案 1 :(得分:0)
我认为,每次插入新的事件对象时,都应该更新storedObjects
,使其现在应该包含插入的对象。
或者更简单地说,您应该将storedObjects
的初始化行放在for循环中。 (这样可以确保从downloadedObjects
开头枚举每个eventObject
的{{1}}上的索引与storedObjects
上的索引相同。但是,关于您的代码,这只会是如果storedObjects
中的所有元素总是在downloadedObjects
中找到,我认为是这种情况,则为true。)
但有一件事,fetchedRecords
应该与storedObjects
相同,如果它们是你应该将storedObjects重新分配为[self.fetchedResultsController fetchedObjects]
,因为它会反映变化在您的上下文中,不执行另一个获取请求,这将解决上述建议的低效率。