使用 NSFetchedResultsController 排序时出现问题

发布于 2024-12-25 05:21:42 字数 2183 浏览 1 评论 0原文

我正在使用 NSFetchedResultsController 来检索 UITableView 的数据。效果很好。现在我需要放置三个按钮,它们应该在表视图上触发不同的排序。为了实现这一目标,我实施了:

switch (selectedOrder) {
    case 0:
        sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
        break;
    case 1: 
        /*
        sortDescriptor = [[NSSortDescriptor alloc] initWithKey: @"price"  ascending: NO 
                                                    comparator: ^(id obj1, id obj2) {
                                                        NSLog(@"Test");
                                                        return numSort(obj1, obj2, nil);
                                                        //return NSOrderedSame;
                                                    }];
         */
        sortDescriptor = [[NSSortDescriptor alloc] initWithKey: @"price" 
                                                     ascending: NO 
                                                      selector:@selector(compareAsFloats:)];

        break;
    ...
    default:
        break;}

我似乎没有找到一种方法来使第二种情况(价格)发挥作用。事实上,如果我使用块,它确实会考虑属性,但作为字符串,而不是数字。就像块中的代码根本没有执行一样。事实上,如果我只是返回 NSOrderedSame 它仍然将其作为字符串排序。并且日志不执行。如果我使用 @selector(compareAsFloats:) 版本,其中该方法是在 NSString 类别上定义的,则会出现运行时错误:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'unsupported NSSortDescriptor selector: compareAsFloats:'
*** Call stack at first throw:
(
    0   CoreFoundation                      0x014df5a9 __exceptionPreprocess + 185
    1   libobjc.A.dylib                     0x01889313 objc_exception_throw + 44
    2   CoreData                            0x01211266 -[NSSQLGenerator newSQLStatementForFetchRequest:ignoreInheritance:countOnly:nestingLevel:] + 1270
    3   CoreData                            0x011494d8 -[NSSQLAdapter _newSelectStatementWithFetchRequest:ignoreInheritance:] + 488
    4   CoreData                            0x011492e1 -[NSSQLAdapter newSelectStatementWithFetchRequest:] + 49
    5   CoreData                            0x0114918e -[NSSQLCore newRowsForFetchPlan:] + 430
    .....   .....
)

我一定犯了一个非常微不足道的错误。 感谢您的帮助。

I am using an NSFetchedResultsController to retrieve data for a UITableView. It works fine. Now I need to place three buttons which should trigger different sorting on the table view. To achieve this I implemented:

switch (selectedOrder) {
    case 0:
        sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
        break;
    case 1: 
        /*
        sortDescriptor = [[NSSortDescriptor alloc] initWithKey: @"price"  ascending: NO 
                                                    comparator: ^(id obj1, id obj2) {
                                                        NSLog(@"Test");
                                                        return numSort(obj1, obj2, nil);
                                                        //return NSOrderedSame;
                                                    }];
         */
        sortDescriptor = [[NSSortDescriptor alloc] initWithKey: @"price" 
                                                     ascending: NO 
                                                      selector:@selector(compareAsFloats:)];

        break;
    ...
    default:
        break;}

I don't seem to find a way to get the second case (price) working. In fact, if I use the block, it does take into account the property, but as a string, not as a number. It is like the code in the block wasn't executed at all. In fact if I just return NSOrderedSame it still orders it as a string. And the log is not performed. If I use the @selector(compareAsFloats:) version, where the method is defined on a NSString category, I get a runtime error:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'unsupported NSSortDescriptor selector: compareAsFloats:'
*** Call stack at first throw:
(
    0   CoreFoundation                      0x014df5a9 __exceptionPreprocess + 185
    1   libobjc.A.dylib                     0x01889313 objc_exception_throw + 44
    2   CoreData                            0x01211266 -[NSSQLGenerator newSQLStatementForFetchRequest:ignoreInheritance:countOnly:nestingLevel:] + 1270
    3   CoreData                            0x011494d8 -[NSSQLAdapter _newSelectStatementWithFetchRequest:ignoreInheritance:] + 488
    4   CoreData                            0x011492e1 -[NSSQLAdapter newSelectStatementWithFetchRequest:] + 49
    5   CoreData                            0x0114918e -[NSSQLCore newRowsForFetchPlan:] + 430
    .....   .....
)

I must be making a very trivial mistake.
Thank you for any help.

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

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

发布评论

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

评论(2

万劫不复 2025-01-01 05:21:42

你不能那样做。如果您使用 SQLite 后端作为核心数据,则排序适用于 SQL 级别。
您不能使用自定义比较选择器或块。您必须仅按实体的属性进行排序

为什么不将价格保存为十进制数字(这是 NSDecimalNumber) 不存在 double 和 float 等精度问题。

然后,您可以仅使用价格来对数据进行排序。

you can't do that. If you use a SQLite backend for Core Data the ordering works on SQL level.
You can't use custom comparison selectors or blocks. You have to solely sort by attributes of your entity

Why don't you save price as a decimal number (that's a NSDecimalNumber) which does not have the accuracy problems like double and float.

You could then just use price to sort your data.

小女人ら 2025-01-01 05:21:42

我实现此目的的方法是在按钮的 IBAction 中定义排序并在 @property 中创建 NSFetchRequest *请求。在按钮操作中我正在这样做:

self.request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"distance" ascending:YES]];
[self.fetchedResultsController performFetch:&error];
[tableView reloadData];

The way I accomplished this was by defining the sort in the IBAction of a button and creating the NSFetchRequest *request in @property. In the button action i am doing this:

self.request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"distance" ascending:YES]];
[self.fetchedResultsController performFetch:&error];
[tableView reloadData];
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文