NSFetchedResultsController 自定义排序未被调用

发布于 2024-10-14 10:11:44 字数 2135 浏览 3 评论 0原文

我目前正在尝试使用 NSFetchedResultsController 从核心数据填充我的项目中的 UITableView。我正在使用带有比较器的自定义搜索(尽管我也尝试过选择器并遇到了相同的问题):

    if (fetchedResultsController != nil) {
        return fetchedResultsController;
    }

    /*
     Set up the fetched results controller.
    */
    // Create the fetch request for the entity.
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    // Edit the entity name as appropriate.
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Object" inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entity];

    // Set the batch size to a suitable number.
    [fetchRequest setFetchBatchSize:20];
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"objectName" ascending:YES comparator:^(id s1, id s2) {
            NSLog(@"Comparator");
      //custom compare here with print statement
    }];
    NSLog(@"Sort Descriptor Set");
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Object" inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entity];
    [fetchRequest setSortDescriptors:sortDescriptors];

    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"firstLetterOfObject" cacheName:@"Objects"];
    [aFetchedResultsController release];
    [fetchRequest release];
    [sortDescriptor release];
    [sortDescriptors release];
    if (![fetchedResultsController performFetch:&error]) {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }

    return fetchedResultsController;

当我进入此选项卡时,我已经记录了整个程序,发现 NSFetchedResultsController 甚至没有进入比较器块获取。相反,它使用某种默认的排序方法对其进行排序。

但是,如果我删除并添加具有 objectName 的对象,它就会进入比较器块并对表进行正确排序。

为什么 NSFetchedResultsController 在托管对象模型更改之前不使用比较器进行排序?

注意:我也尝试过关闭缓存和/或在 viewDidLoad: 中执行提取,但似乎提取多少次并不重要,重要的是何时。由于某种原因,它仅在对象模型更改后才使用我的排序。

I am currently trying to populate a UITableView in my project from Core Data using NSFetchedResultsController. I am using a custom search with a comparator (although I have also tried a selector and had an identical problem):

    if (fetchedResultsController != nil) {
        return fetchedResultsController;
    }

    /*
     Set up the fetched results controller.
    */
    // Create the fetch request for the entity.
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    // Edit the entity name as appropriate.
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Object" inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entity];

    // Set the batch size to a suitable number.
    [fetchRequest setFetchBatchSize:20];
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"objectName" ascending:YES comparator:^(id s1, id s2) {
            NSLog(@"Comparator");
      //custom compare here with print statement
    }];
    NSLog(@"Sort Descriptor Set");
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Object" inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entity];
    [fetchRequest setSortDescriptors:sortDescriptors];

    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"firstLetterOfObject" cacheName:@"Objects"];
    [aFetchedResultsController release];
    [fetchRequest release];
    [sortDescriptor release];
    [sortDescriptors release];
    if (![fetchedResultsController performFetch:&error]) {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }

    return fetchedResultsController;

When I enter this tab, I have logged all over the program and found that the NSFetchedResultsController does not even enter the comparator block when fetching. It instead sorts it with some default sorting method.

If I delete and add an Object with an objectName, however, it then does enter the comparator block and correctly sort the table.

Why does the NSFetchedResultsController not sort using the comparator until the managed object model is changed?

Notes: I have tried also turning off caching, and/or performing a fetch in viewDidLoad:, but it seems that how many times I fetch does not matter, but when. For some reason it only uses my sorting after the object model has been changed.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

乱世争霸 2024-10-21 10:11:44

我能想到一些事情。首先,虽然这可能不是您的问题,但您无法对瞬态属性进行排序。但更有可能的是,当在 SQL 存储支持的模型中进行排序时,比较器被“编译”为 SQL 查询,并且并非所有 Objective-C 函数都可用。在这种情况下,您需要在执行提取后在内存中进行排序。

编辑:请参阅此doc,特别是获取谓词和排序描述符部分。

There are a couple of things I can think of. First, though this may not be your problem, you cannot sort on transient properties. But more likely is that when sorting in a model backed by a SQL store, the comparator gets "compiled" to a SQL query, and not all Objective-C functions are available. In this case, you'd need to sort in memory after the fetch is performed.

EDIT: See this doc, specifically the Fetch Predicates and Sort Descriptors section.

兔姬 2024-10-21 10:11:44

我看到同样的问题,解决该问题的方法是修改对象,保存更改,然后将其恢复到原始值并再次保存。

    // try to force an update for correct initial sorting bug
NSInteger count = [self.fetchedResultsController.sections count];
if (count > 0) {
    id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:0];
    count = [sectionInfo numberOfObjects];
    if (count > 0) {
        NSManagedObject *obj = [self.fetchedResultsController objectAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
        NSString *name = [obj valueForKey:@"name"];
        [obj setValue:@"X" forKey:@"name"];
        // Save the context.
        [self saveContext];
        [obj setValue:name forKey:@"name"];
        // Save the context.
        [self saveContext];
    }
}

I see the same problem and a way to work around it is to modify an object, save the change then restore it to its original value and save again.

    // try to force an update for correct initial sorting bug
NSInteger count = [self.fetchedResultsController.sections count];
if (count > 0) {
    id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:0];
    count = [sectionInfo numberOfObjects];
    if (count > 0) {
        NSManagedObject *obj = [self.fetchedResultsController objectAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
        NSString *name = [obj valueForKey:@"name"];
        [obj setValue:@"X" forKey:@"name"];
        // Save the context.
        [self saveContext];
        [obj setValue:name forKey:@"name"];
        // Save the context.
        [self saveContext];
    }
}
浮生面具三千个 2024-10-21 10:11:44

抱歉,您是否错过了代码片段的最终获取部分?:

NSError *error;
BOOL success = [aFetchedResultsController performFetch:&error];

也不要忘记释放请求:

[fetchRequest release];

Sorry, but did you miss the final fetch part to your code snippet?:

NSError *error;
BOOL success = [aFetchedResultsController performFetch:&error];

Don't forget to release the request too:

[fetchRequest release];
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文