【问题标题】:Sorting NSFetchedResultsController using a to-many relationship property使用一对多关系属性对 NSFetchedResultsController 进行排序
【发布时间】:2013-07-21 14:27:07
【问题描述】:

场景

我有两个实体:ItemListDetail(其中包含每个项目的不同列表的价格)。这是绝对需要的,我无法为 Item 实体提供价格属性,因为每个项目都可以为不同的动态列表(零售、b2b ecc)提供更多价格。

关系是:

Item (lists) <------->> (item) ListDetail

我的应用程序中的当前活动列表会发生动态变化,因此假设我有一个包含当前活动列表的整数变量:_ACTIVE_LIST_CODE_。当我需要商品对象的价格时,我会在 Item 类上使用辅助方法:

-(NSNumber*) getPrice {
    NSSet *lists=[self.lists filteredSetUsingPredicate: [NSPredicate predicateWithFormat:@"listId == %d",_ACTIVE_LIST_CODE_]]; 
    ListDetail *activeList=[[lists allObjects] objectAtIndex:0];
    return activeList.price;
}

问题

我使用带有 NSFetchedResultController 的 UITableView 来选择和显示不同部分的一些项目。没什么特别的。我想使用活动列表的项目价格订购 fetchedObjects。如果价格是 Item 的一个属性,我会像这样在 fetch 请求中简单地添加一个排序描述符:

[NSSortDescriptor sortDescriptorWithKey:@"price" ascending:YES];

但正如之前所说,这是不可能的,价格是一个动态属性。

如果排序描述符可以使用瞬态属性,我将使用我的辅助方法设置一个动态计算的价格瞬态属性。无事可做。

不可能在描述符中使用像“lists.price”这样的键路径(或者我可能不知道该怎么做),因为它是一对多的关系,并且是用 NSSet 建模的。

我尝试了一些解决方法,但没有成功:

1) 观察 _ACTIVE_LIST_CODE_ 更改以在非瞬态属性中设置项目价格。

2) 在获取请求之后,在呈现表视图之前,使用瞬态“price”属性重新排序一个包含获取对象的全新数组,在升序整数索引“i”之后迭代排序数组并将此值分配给Item 实体的非瞬态属性“order”。在获取请求中使用“order”作为排序描述符。 (这里描述了这种方法:Re-ordering NSFetchedResultsController

它们都可以工作,但它们会降低性能,因为我在提取结果中有数千个项目......有什么想法吗?

【问题讨论】:

  • 1) 如何减慢速度?活动列表代码应该不会频繁或大量更改,对吧?
  • 当用户选择不同的客户端时,列表代码可能会改变。这种情况发生的频率并不高,但即使一次,对 50k 项进行 for 循环、更改价格属性并保存上下文也会使应用程序冻结 8-9 秒。这是不可接受的!
  • 您可以在后台线程上进行更新,并通过 NSFetchedResultsControllerDelegate 更新 UI。
  • 当然可以,但这不是一个很大的优势:项目需要在客户选择后立即显示(这意味着活动列表更改),所以我需要更新价格属性并对项目进行排序按价格。
  • 这不合逻辑。要么有设备更改--> 巨大更新--> 后台线程。或者有一个活动列表更改--> 小更新--> 立即从 bg 线程返回。

标签: core-data one-to-many nsfetchedresultscontroller nsfetchrequest nssortdescriptor


【解决方案1】:

改为获取ListDetail 怎么样?您可以完全按照您的建议使用适当的谓词和排序描述符进行限制和排序。

fetchRequest.predicate = 
  [NSPredicate predicateWithFormat:@"listID = %@", activeListCode];

fetchRequest.sortDescriptors = 
  @[[NSSortDescriptor sortDescriptorWithKey:@"price" ascending:YES]];

现在,按项目的某些属性进行分组应该是简单而有效的,因为它是一对一的关系。您获取的结果控制器的 sectionNameKeyPath 可能类似于

@"item.category"

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多