从关系中观察 sectionNameKeyPath 的变化
Observe to sectionNameKeyPath changes when from relationship
什么是确保对 sectionKeyPathName
值(来自相关实体)的更改传播到 UITableView 的 header 部分(包括重绘部分 header 是否具有新值并根据需要更改部分顺序)?
我假设 NSFetchedResultsController 委托的当前功能不能满足我的需求,因为
NSFetchedResultsController
正在观察一个实体(Recipe 在我的例子中是 table 行)而不是 [=10= 的实体] (类别 的名字 属性 对我来说。)
NSFetchedResultsController
委托的 controller(_:didChange:atSectionIndex:for)
从不 returns 移动 或 更新 其类型参数
背景
我有两个实体,Category 和 Recipe,其中一个 Category 可以有多个 Recipes 而一个 Recipe 将只属于 1 个 Category(又名 1:M 关系。)
我有一个 table 食谱视图,每个类别都有一个部分。 header 部分是类别的名称。我使用了 fetchedResultsController 来填充 table 视图。一切都按预期工作(即,当食谱被更新、添加、删除或更改其类别时,table 视图反映了这些更改),只有一个例外。当类别名称更改时,我无法更改 headers 部分。我不仅希望 header 反映更改后的名称,而且还希望根据需要反映 re-sort。
代码片段
我会根据需要分享。正如我所说,其他一切都有效,并且有很多代码。
FWIW - 我的 sectionKeyPathName
值与 sortDescriptor 数组的第一个值相同。
尝试失败
我假设我需要 观察 类别的 name
属性 以了解变化。最坏的情况是,我的部分需要 re-ordering。因此,如果 name
改变了,我会再次 performFetch()
然后 reloadData()
在 table 上。我试过这个技巧。
- 观察
NSManagedObjectContextWillSave
以确定类别(当前是我 table 视图中的一个部分)是否有 name
属性 变化。
- 如果
name
属性改变了,那么当我观察到NSManagedObjectContextDidSave
时,我会再次执行fetch和reloadData()。这似乎解决了问题,但当我测试将食谱移动到不同的类别时崩溃了。 (移动测试在此更改之前有效。)(崩溃是 An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:. Invalid update: invalid number of sections.
)
fetchedResultsController 很棒。但他们并不是超级聪明。它们仅监视设置为获取的实体的更改。它假设所有其他更改都不会影响它。因此,如果您有基于关系的谓词或排序描述符,它可能会导致问题。
可能的解决方案:
1) 列出类别而不是食谱
即使 fetchedResultsController 被设计为在带有 tableview 或 collectionView 的 1:1 设置中很好地工作(即 fetchedResultsController 的 indexPath 等于视图的 indexPath)它不需要工作方法。
您可以为没有 sectionKeyPathName 的类别创建一个 fetchedResultsController。然后设置节数为控制器中的项目数。每个部分中的项目数等于每个类别中的食谱数。
如果您有过滤食谱的谓词,这会变得更加困难。
2) 当有变化时触发fetchedResultsController
如果您只在少数几个地方更改类别,则可能很容易简单地 'dirty' 类别中的所有食谱来触发 fetchedResultsController。如果您将 属性 设置为等于自身(即 r.recipeId = r.recipeId),它将触发 fetchedResultsController 中的更新。因此,当您更改 categoryName 时,也会遍历所有食谱并将它们弄脏。
3) 有两个 fetchedResultsController
FetchedResultsController 是非常轻的对象,您无需担心根据需要制作尽可能多的对象。你可以创建两个。一份用于食谱,一份用于类别。这些部分基于类别 fetchedResultsController。对于配方 fetchedResultsController,您可以根据 属性 不变的类别(例如 categoryId)对其进行分组。然后当你想知道一个类别的 numberOfRows 时,你必须在配方 fetchedResultsController 中找到它。弄清楚 indexPath 可能有点烦人——但如果你创建一个单独的对象来管理它,这没什么大不了的。
如果您要展示所有食谱,我会推荐 #1。如果你对你的食谱有判断力,我会推荐#2。如果您是代码纯粹主义者并且希望完全分离您的模型和您的视图,我只会推荐#3。
什么是确保对 sectionKeyPathName
值(来自相关实体)的更改传播到 UITableView 的 header 部分(包括重绘部分 header 是否具有新值并根据需要更改部分顺序)?
我假设 NSFetchedResultsController 委托的当前功能不能满足我的需求,因为
NSFetchedResultsController
正在观察一个实体(Recipe 在我的例子中是 table 行)而不是 [=10= 的实体] (类别 的名字 属性 对我来说。)NSFetchedResultsController
委托的controller(_:didChange:atSectionIndex:for)
从不 returns 移动 或 更新 其类型参数
背景
我有两个实体,Category 和 Recipe,其中一个 Category 可以有多个 Recipes 而一个 Recipe 将只属于 1 个 Category(又名 1:M 关系。)
我有一个 table 食谱视图,每个类别都有一个部分。 header 部分是类别的名称。我使用了 fetchedResultsController 来填充 table 视图。一切都按预期工作(即,当食谱被更新、添加、删除或更改其类别时,table 视图反映了这些更改),只有一个例外。当类别名称更改时,我无法更改 headers 部分。我不仅希望 header 反映更改后的名称,而且还希望根据需要反映 re-sort。
代码片段
我会根据需要分享。正如我所说,其他一切都有效,并且有很多代码。
FWIW - 我的 sectionKeyPathName
值与 sortDescriptor 数组的第一个值相同。
尝试失败
我假设我需要 观察 类别的 name
属性 以了解变化。最坏的情况是,我的部分需要 re-ordering。因此,如果 name
改变了,我会再次 performFetch()
然后 reloadData()
在 table 上。我试过这个技巧。
- 观察
NSManagedObjectContextWillSave
以确定类别(当前是我 table 视图中的一个部分)是否有name
属性 变化。 - 如果
name
属性改变了,那么当我观察到NSManagedObjectContextDidSave
时,我会再次执行fetch和reloadData()。这似乎解决了问题,但当我测试将食谱移动到不同的类别时崩溃了。 (移动测试在此更改之前有效。)(崩溃是An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:. Invalid update: invalid number of sections.
)
fetchedResultsController 很棒。但他们并不是超级聪明。它们仅监视设置为获取的实体的更改。它假设所有其他更改都不会影响它。因此,如果您有基于关系的谓词或排序描述符,它可能会导致问题。
可能的解决方案:
1) 列出类别而不是食谱
即使 fetchedResultsController 被设计为在带有 tableview 或 collectionView 的 1:1 设置中很好地工作(即 fetchedResultsController 的 indexPath 等于视图的 indexPath)它不需要工作方法。
您可以为没有 sectionKeyPathName 的类别创建一个 fetchedResultsController。然后设置节数为控制器中的项目数。每个部分中的项目数等于每个类别中的食谱数。
如果您有过滤食谱的谓词,这会变得更加困难。
2) 当有变化时触发fetchedResultsController
如果您只在少数几个地方更改类别,则可能很容易简单地 'dirty' 类别中的所有食谱来触发 fetchedResultsController。如果您将 属性 设置为等于自身(即 r.recipeId = r.recipeId),它将触发 fetchedResultsController 中的更新。因此,当您更改 categoryName 时,也会遍历所有食谱并将它们弄脏。
3) 有两个 fetchedResultsController
FetchedResultsController 是非常轻的对象,您无需担心根据需要制作尽可能多的对象。你可以创建两个。一份用于食谱,一份用于类别。这些部分基于类别 fetchedResultsController。对于配方 fetchedResultsController,您可以根据 属性 不变的类别(例如 categoryId)对其进行分组。然后当你想知道一个类别的 numberOfRows 时,你必须在配方 fetchedResultsController 中找到它。弄清楚 indexPath 可能有点烦人——但如果你创建一个单独的对象来管理它,这没什么大不了的。
如果您要展示所有食谱,我会推荐 #1。如果你对你的食谱有判断力,我会推荐#2。如果您是代码纯粹主义者并且希望完全分离您的模型和您的视图,我只会推荐#3。