2013-09-16 3 views
2

У меня есть этот кусок кода:XCode iOS6 CoreData NSFetchedResultsController не может принести новые данные

- (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 и перезагрузке из базы данных набор записей должен быть изменен из-за предыдущего обновления, поэтому, когда пользователь повторно коснется одной и той же ячейки, нет необходимости получать данные из Интернета, так как мы уже выполнили данные для выбранной ячейки. Но ... как я объяснил выше, NSFetchResultController не дал новых данных, даже после обновления файла SQLITE!

+0

Не понимаю, почему вы меняете базу данных извне, используя какой-либо сторонний редактор базы данных? –

+0

Я обновил вопрос, см. Выше – DeckyFx

ответ

3

ОК, извините за длинный перерыв, вот как я решаю свою проблему для тех, кто сталкивается с этой проблемой в будущем, все кредиты передаются всем здесь, спасибо.

При выполнении выборки запроса убедитесь, удалить старый кэш

[NSFetchedResultsController deleteCacheWithName:nil]; 

Тогда для всех извлеченного объекта в fetchResultController, вызовите refreshObject с опцией mergeChanges ДА

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

это обеспечит вам получить новые данные каждый раз, когда выполняется запрос на выборку

1

Основные данные отслеживают объекты объекта в памяти, но ленивы загружают фактические значения атрибутов. Акт ленивой загрузки называется неисправностью. Если вы изменяете значение атрибута непосредственно в хранилище, а затем генерируется ошибка для соответствующего управляемого объекта, измененные значения будут загружены в память. Управляемые объекты будут сохраняться в памяти до тех пор, пока они больше не понадобятся. Core Data предполагает, что он имеет контроль над хранилищем и не будет пытаться повторно загрузить значения атрибута управляемого объекта, пока объект не будет признан недействительным, и для него будет произведена другая ошибка. Поэтому, если вы измените значение после того, как управляемый объект уже был заполнен для записи, изменения не будут немедленно отображаться. Вам нужно будет понять поведение и время жизни управляемых объектов для разработки, когда ожидать, что изменения будут представлены в памяти.

Также будьте осторожны, чтобы не вносить изменения непосредственно в магазин во время работы приложения, а затем взаимодействовать с приложением так, чтобы он вносил изменения в базу данных. Если Core Data необходимо обновить измененную запись, она будет считать (правильно, что при обычных условиях), что она имеет исключительный контроль и перезапишет ваши скрытые изменения данными из управляемых в памяти объектов.

+0

Хорошо, спасибо за ваш ответ. так же, как я объяснил, я напрямую изменяю данные только для тестирования, проблема по-прежнему возникает, даже я обновляю данные с помощью кода, поэтому он просто упрощен. так как предотвратить эту ошибку? Я хочу, чтобы данные ядра всегда читались из реальной базы данных. – DeckyFx

+0

Добро пожаловать. если вы думаете, что я ответил на ваш вопрос, пожалуйста, примите его, чтобы помочь другим, у кого такая же проблема. Спасибо – samir

+0

Я не знаю, можно ли изменить поведение. Образцом и безопасным решением является повторное использование вашего приложения после каждой модификации вашей базы данных SQLite. – samir

Смежные вопросы