XCode iOS6 CoreData NSFetchedResultsController无法获取新数据

时间:2013-09-16 04:37:34

标签: ios objective-c xcode sqlite core-data

我有这段代码:

- (void) fetchRecordsStaringFrom:(double)start limit:(double)limit whereFields:(NSArray*)whereFields haveValues:(NSArray*)whereValues sortBy:(NSString*)sortField ascending:(BOOL)isascending delegateEvent:(BOOL)delegateEvent{
NSFetchRequest *_fetchRequest = [[NSFetchRequest alloc] init];
[_fetchRequest setEntity:self.entityDescription];
// Create the sort descriptors array.
// Default sort is ID
if (sortField == NULL) {
    sortField = @"id";
}
NSSortDescriptor *authorDescriptor = [[NSSortDescriptor alloc] initWithKey:sortField ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:authorDescriptor, nil];
[_fetchRequest setSortDescriptors:sortDescriptors];
if (whereFields != Nil && whereValues != Nil && ([whereFields count] == [whereValues count])) {
    NSMutableString *predicateString = [[NSMutableString alloc] initWithString:@""];
    for (int index = 0; index < [whereFields count]; index++) {
        [predicateString appendFormat:@"%@==%@", whereFields[index], whereValues[index]];
        if (index < [whereFields count] - 1) {
            [predicateString appendString:@" AND "];
        }
    }
    // Delete old cache to make sure always get new data
    [NSFetchedResultsController deleteCacheWithName:nil];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:predicateString];
    [_fetchRequest setPredicate:predicate];
} else {
}
self.fetchRequest = _fetchRequest;
self.fetchResultController = [[NSFetchedResultsController alloc] initWithFetchRequest:self.fetchRequest managedObjectContext:self.context sectionNameKeyPath:nil cacheName:nil];
self.fetchResultController.delegate = self;
NSError *_error;
if (delegateEvent) {
    if ([self.delegate respondsToSelector:@selector(CoreDataEntityRequestStartEvent:::)]) {
        [self.delegate CoreDataEntityRequestStartEvent:self :self.fetchRequest :self.fetchResultController];
    }
    if (![self.fetchResultController performFetch:&_error]) {
        if ([self.delegate respondsToSelector:@selector(CoreDataEntityRequestErrorEvent::)]) {
            [self.delegate CoreDataEntityRequestErrorEvent:self :_error];
        }
    } else {
        if ([self.delegate respondsToSelector:@selector(CoreDataEntityRequestSuccessEvent:::)]) {
            [self.delegate CoreDataEntityRequestSuccessEvent:self :self.fetchRequest :self.fetchResultController];
        }
    }
    if ([self.delegate respondsToSelector:@selector(CoreDataEntityRequestEndEvent:::)]) {
        [self.delegate CoreDataEntityRequestEndEvent:self :self.fetchRequest :self.fetchResultController];
    }
} else {
    [self.fetchResultController performFetch:&_error];
}
}

执行时,上面的方法将从SQLITE数据库中获取数据,这里没问题, 但是当我使用外部SQLITE编辑器或其他方式更改SQLITE,然后使用相同的参数再次执行时,它无法获取新数据并保留旧数据,除非我重新启动应用程序。

我在这里和那里看,这可能是因为缓存,但正如你所看到的,我已经清除了缓存,但仍然无法获得新数据。


感谢您的回复, 答案是:仅供测试,

这是实际案例: 例如,在屏幕UITableView中,从互联网获取数据(数据不完整),将其存储在数据库中然后加载并显示在视图中,然后当一个单元格点击时,将从互联网获取所选单元格的完整数据,更新数据库,并将其显示在其他屏幕中。当返回到UItableView并从数据库重新加载时,记录集应该在之前更新时更改,因此当用户在同一个单元重新点击时,不需要从Internet获取数据,因为我们已经完成了所选单元的数据。但是......正如我上面解释的那样,即使在更新SQLITE文件之后,NSFetchResultController也没有提供新数据!

2 个答案:

答案 0 :(得分:3)

好的,对不起长时间休息,这就是我如何为将来遇到这个问题的人解决我的问题,所有的积分都归到了这里,谢谢。

执行获取请求时,请确保删除旧缓存

[NSFetchedResultsController deleteCacheWithName:nil];

然后对于fetchResultController中的所有获取对象,使用选项mergeChanges YES调用refreshObject

for (int i = 0; i < [[self.fetchResultController fetchedObjects] count]; i++) {
[self.context refreshObject:[[self.fetchResultController fetchedObjects] objectAtIndex:i] mergeChanges:YES];
}

这将确保您每次执行获取请求时都能获得新数据

答案 1 :(得分:1)

Core Data跟踪内存中的实体对象,但延迟加载实际属性值。延迟加载的行为称为断层。如果直接在存储中修改属性值,然后为相应的受管对象触发错误,则更改的值将加载到内存中。然后,托管对象将持续存储在内存中,直到不再需要为止。 Core Data假定它具有对存储的控制权,并且在对象失效并为其触发另一个错误之前不会再次尝试加载受管对象属性值。因此,如果在已为记录填充托管对象后更改值,则不会立即显示更改。您需要了解托管对象的行为和生命周期,以确定何时期望更改在内存中表示。

另外要小心,不要在应用程序运行时直接对商店进行更改,然后以提交更改数据库的方式与应用程序进行交互。如果Core Data需要更新您修改过的记录,它将假定(在正常情况下正确)它具有独占控制权,并将使用来自内存中管理对象的数据覆盖您的偷偷摸摸的更改。