核心数据不会对更改的谓词做出反应 [英] Core Data does not react on changed predicate

查看:27
本文介绍了核心数据不会对更改的谓词做出反应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一个奇怪的问题.

在我的视图控制器 SpieleOrtTVC 中,我将展示实体 Spiel 的对象子集.每次调用视图控制器时,都应根据用户在呈现视图控制器中的选择显示不同的子集.

In my view controller SpieleOrtTVC I am going to present a subset of the objects of the entity Spiel. Every time the view controller is called a different subset should be displayed based on the users's selection within the presenting view controller.

这对于第一次调用视图控制器时效果很好.根据用户的选择,获取 creteria 被移交给新的视图控制器,并且实际上正确地到达那里,正如 NSLogs 所证明的那样.显示的结果和数据与预期一致.

This works just well for each first time the view controller is called. Depending on the user's selection, fetch creteria is handed over to the new view controller and actually arrives there correctly, as the NSLogs prove. The result and data displayed is as expeted.

但是当视图控制器被第二次或第三次调用时,正确的获取标准也会被传递给视图控制器,但显然获取结果对应于之前执行的获取.

But when the view controller is called a second or third time, then, too, the correct fetch criteria is handed to the view controller but aparenty the fetch result corresponds to the fetch that was performed earlier.

这是代码.SpieleOrtTVC 从地图标注中调用.所选对象的名称恰好在注释的标题中,将移交给新实例化的 SpieleOrtTVC.

This is the code. SpieleOrtTVC is called out of a map callout. The selected object's name, which happens to be in the annotation's title, is handed over to the newly instanciated SpieleOrtTVC.

带有地图的调用视图控制器:

The calling view controller with a map:

- (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:

SpieleOrteTVC.h:

@property (strong, nonatomic) NSString *ortName;
@property (strong, nonatomic) NSString *stadionName;

(只是一个属性,没有 getter 或 setter 等,自动合成)

(Just a property, no getters or setters etc, auto-synthesized)

这是我怀疑 SpieleOrteTVC.m 的一段代码:

This is the piece of code that I doubt of 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

这是下一次调用的结果,用户选择不同:

And this is the next call's result, with a different user selection:

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

它清楚地表明,不同的选择标准是从用户的交互中正确获取的,并传递给新的视图控制器.特别是 fetch 请求会相应地设置其谓词,但两种情况下的结果都是相同的.(此处用于示例的时间戳对于所有对象都是唯一的)

It shows clearly that the different selection criteria is taken correctly from the user's interaction and handed down to the new view controller. Especially the fetch request gets its predicate set accordingly but the results are the same in both cases. (the timestamp used for the sample here are unique for all objects)

这里有什么问题?

我很高兴分享更多代码.请告诉我您认为与该问题相关的内容.

I am happy to share more code. Just tell me what you think is relevant for the question.

如果这很重要:iOS 7.1.1,在设备上运行(iPhone 4、4S、5、iPad mini - 都一样),Xcode 5.1.1

If that is of importance: iOS 7.1.1, running on the device (iPhone 4, 4S, 5, iPad mini - all the same), Xcode 5.1.1

(我确实有一个方便的解决方法,但出于好奇,我想知道问题是什么.)

(I do have a workaround handy, but out of curiosity I'd like to know what the problem is.)

推荐答案

来自 NSFetchedResultsController 参考:

重要提示:如果您使用缓存,则必须调用deleteCacheWithName: 在更改任何获取请求之前,其谓词,或其排序描述符.您不得重复使用相同的获取多个查询的结果控制器,除非您设置cacheName 为 nil.

Important: If you are using a cache, you must call deleteCacheWithName: before changing any of the fetch request, its predicate, or its sort descriptors. You must not reuse the same fetched results controller for multiple queries unless you set the cacheName to nil.

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

So the problem in your case is that the FRC re-uses a cache that was created for a different predicate. Either don't use a cache (cacheName:nil) or delete the cache before the new FRC is created. In your situation, a cache probably does not make much sense.

这篇关于核心数据不会对更改的谓词做出反应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆