这是一个奇怪的问题。
在我的视图控制器SpieleOrtTVC
中,我将呈现实体Spiel
的对象的子集。每次调用视图控制器时,都应根据用户在呈现视图控制器中的选择来显示不同的子集。
这适用于每次第一次调用视图控制器时。根据用户的选择,fetch creteria被移交给新的视图控制器并实际到达那里,正如NSLogs所证明的那样。显示的结果和数据已经过时。
但是当第二次或第三次调用视图控制器时,也会将正确的提取标准传递给视图控制器,但是获取结果对应于先前执行的提取。
这是代码。 SpieleOrtTVC被称为地图标注。所选对象的名称恰好在注释的标题中,被移交给新实例化的SpieleOrtTVC。
带有地图的调用视图控制器:
- (void)mapView:(MKMapView *)mv annotationView:(MKAnnotationView *)pin calloutAccessoryControlTapped:(UIControl *)control {
SpieleOrtTVC *detailViewController = [self.storyboard instantiateViewControllerWithIdentifier:STORYBOARD_ID_SPIELE_ORT];
MKPointAnnotation *theAnnotation = (MKPointAnnotation *) pin.annotation;
NSLog(@"the Annotation %@",theAnnotation.title);
detailViewController.ortName = theAnnotation.title;
detailViewController.stadionName = theAnnotation.subtitle;
[self presentViewController:detailViewController animated:YES completion:nil];
}
SpieleOrteTVC.h:
@property (strong, nonatomic) NSString *ortName;
@property (strong, nonatomic) NSString *stadionName;
(只是一个属性,没有getter或setter等,自动合成)
这是我怀疑SpieleOrteTVC.m的代码:
- (NSManagedObjectContext *) managedObjectContext {
if (! _managedObjectContext) {
_managedObjectContext = [(AppDelegate*) [[UIApplication sharedApplication] delegate] managedObjectContext];
}
return _managedObjectContext;
}
- (NSFetchedResultsController *)fetchedResultsController
{
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:[self entityName] inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
// Set the batch size to a suitable number.
[fetchRequest setFetchBatchSize:20];
// Edit the sort key as appropriate.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:[self sortDescriptorString] ascending:[self sortAscending]];
NSArray *sortDescriptors = @[sortDescriptor];
[fetchRequest setSortDescriptors:sortDescriptors];
[fetchRequest setPredicate:[self predicate]];
// Edit the section name key path and cache name if appropriate.
// nil for section name key path means "no sections".
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:@"Master"];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error]) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
NSLog(@"request: %@", fetchRequest);
for (NSManagedObject *mo in [_fetchedResultsController fetchedObjects]) {
NSLog(@"fetched: %@", [mo valueForKey:ATTRIB_ANSTOSS]);
}
- (NSString *) entityName {
return ENTITY_SPIEL;
}
- (NSString *) sortDescriptorString{
return ATTRIB_ANSTOSS;
}
- (NSPredicate *) predicate {
return [NSPredicate predicateWithFormat:@"(spielOrt.name == %@)", self.ortName];
}
- (BOOL) sortAscending {
return YES;
}
第一次通话的输出:
2014-05-11 13:49:16.209 myApp[2745:60b] the Annotation Porto Alegre
2014-05-11 13:49:21.937 myApp[2745:60b] request: <NSFetchRequest: 0x18c0c960> (entity: Spiel; predicate: (spielOrt.name == "Porto Alegre"); sortDescriptors: ((
"(anstoss, ascending, compare:)"
)); batch size: 20; type: NSManagedObjectResultType; )
2014-05-11 13:49:21.955 myApp[2745:60b] fetched: 2014-06-15 19:00:51 +0000
2014-05-11 13:49:21.957 myApp[2745:60b] fetched: 2014-06-18 16:00:52 +0000
2014-05-11 13:49:21.959 myApp[2745:60b] fetched: 2014-06-22 19:00:51 +0000
2014-05-11 13:49:21.960 myApp[2745:60b] fetched: 2014-06-25 16:00:51 +0000
2014-05-11 13:49:21.962 myApp[2745:60b] fetched: 2014-06-30 20:00:04 +0000
这是下一个电话的结果,用户选择不同:
2014-05-11 13:50:25.654 myApp[2745:60b] the Annotation Fortaleza
2014-05-11 13:50:25.675 myApp[2745:60b] request: <NSFetchRequest: 0x18c6c0e0> (entity: Spiel; predicate: (spielOrt.name == "Fortaleza"); sortDescriptors: ((
"(anstoss, ascending, compare:)"
)); batch size: 20; type: NSManagedObjectResultType; )
2014-05-11 13:50:25.681 myApp[2745:60b] fetched: 2014-06-15 19:00:51 +0000
2014-05-11 13:50:25.683 myApp[2745:60b] fetched: 2014-06-18 16:00:52 +0000
2014-05-11 13:50:25.684 myApp[2745:60b] fetched: 2014-06-22 19:00:51 +0000
2014-05-11 13:50:25.686 myApp[2745:60b] fetched: 2014-06-25 16:00:51 +0000
2014-05-11 13:50:25.687 myApp[2745:60b] fetched: 2014-06-30 20:00:04 +0000
清楚地表明,从用户的交互中正确地采用了不同的选择标准,并将其传递给新的视图控制器。特别是获取请求相应地获得其谓词集,但结果在两种情况下都是相同的。 (此处用于示例的时间戳对于所有对象都是唯一的)
这里有什么问题?
我很乐意分享更多代码。告诉我您认为与此问题相关的内容。
如果这很重要:iOS 7.1.1,在设备上运行(iPhone 4,4S,5,iPad mini - 都一样),Xcode 5.1.1
(我确实有一个方便的解决方法,但出于好奇,我想知道问题所在。)
答案 0 :(得分:7)
来自NSFetchedResultsController
参考:
重要提示:如果您使用的是缓存,则必须致电 在更改任何获取请求之前
deleteCacheWithName:
谓词或其排序描述符。你不能重复使用它 除非您设置了,否则为多个查询提取结果控制器 cacheName为nil
。
因此,您的问题是FRC重新使用为a创建的缓存
不同的谓词。要么不使用缓存(cacheName:nil
),要么删除
在创建新FRC之前缓存。在您的情况下,缓存可能不会
很有道理。