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

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

问题描述

这是一个奇怪的问题。

This is a strange issue.

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

这对于每次第一次调用视图控制器都适用。根据用户的选择,fetch creteria被移交到新的视图控制器,并实际到达那里,正如NSLogs证明。显示的结果和数据为expeted。

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.

但是当第二次或第三次调用视图控制器时,也将正确的提取标准提交给视图控制器,但是aparenty的提取结果对应于提前执行。

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;

(只是属性,没有getters或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

它清楚地示出了从用户的交互中正确地采用不同的选择标准并传递给新的视图控制器。特别地,获取请求相应地获得其谓词集合,但是在这两种情况下结果相同。
(此处示例的时间戳对所有对象都是唯一的)

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重用一个为
不同的谓词创建的缓存。在创建新的FRC之前,不要使用缓存( cacheName:nil )或删除
缓存。在你的情况下,缓存可能不会使
有意义。

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天全站免登陆