核心数据不会对更改的谓词做出反应

时间:2014-05-11 11:55:47

标签: ios objective-c core-data nsfetchedresultscontroller

这是一个奇怪的问题。

在我的视图控制器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

(我确实有一个方便的解决方法,但出于好奇,我想知道问题所在。)

1 个答案:

答案 0 :(得分:7)

来自NSFetchedResultsController参考:

  

重要提示:如果您使用的是缓存,则必须致电   在更改任何获取请求之前deleteCacheWithName:   谓词或其排序描述符。你不能重复使用它   除非您设置了,否则为多个查询提取结果控制器   cacheName为nil

因此,您的问题是FRC重新使用为a创建的缓存 不同的谓词。要么不使用缓存(cacheName:nil),要么删除 在创建新FRC之前缓存。在您的情况下,缓存可能不会 很有道理。

相关问题