TL; DR - 为了简化整个描述,当核心数据对象属性在后台频繁更新时,如何实现基于非基于tableview的视图控制器UI。因此,视觉数据表示需要立即更新。 [在tableview中它很容易处理,你使用FRC并在对象更新时通过FRC委托方法重新加载行。]
我了解NSFetchedResultsController
并将其映射到用户界面。但仅当用户界面基于列表时才会这样。
在我的情况下,类似类型的多个硬件通过蓝牙(BLE)连接到我的应用程序,并且每个通常提供频率为1秒的更新。 E.g温度,电荷变化。
所以这是UI流程的一个例子,
列表 - >细节
详细
详细信息仅代表与硬件相关的数据(序列号,固件版本,制造日期等),并且它有3个按钮,这些按钮在点击时会按下相应的控制器。
实体模型也是相应设计的,这里有一瞥,我有一个主要实体让我们说ABC
。然后,ABC
与其他实体(如HealthDetails
,Activity
,NotificationSetting
和HardwareDetails
具有一对一的关系。 ABC
的属性很少,如identifier
,connected
,name
等。
ListViewController
是UITableViewController
,因此我使用NSFetchedResultsController
。现在剩下的所有其他视图控制器都只是普通的视图控制器,只有标题标签,如“最后收费日期”,这是静态的,并且描述标签是'在它下面显示数据。其他视图控制器也类似地只用按钮,标签等填充。
使用NSFetchedResultsController
可以轻松更新列表视图控制器。
[当用户点击行/单元格时,我只是使用FRC中的索引路径获取对象并将其注入目标视图控制器。]
但是其他视图控制器不是基于表视图的。所以我使用通知来控制其他视图控制器UI更新。
例如,当我的BluetoothManager
从硬件收到有关特征的更新时,我将特征ID和数据通道化到我的DatabaseHelper
,然后解码数据并插入到相应的管理对象中,此时我只是用一个更新的对象的标识符发出通知。
层次结构中位于导航堆栈中的所有UIViewController
都被订阅为观察者。如果通知中的标识符与当前显示的实体对象匹配,那么我刷新UI。目前这一切都很好。
但是,我觉得它非常笨拙,处理大量通知。这是唯一的方法还是存在更好的方法将各个核心数据模型紧密地耦合到UI?
我看到几条评论建议仅通过FRC处理所有问题,但我不确定FRC是否可用于基于非基于tableview的UI表示。我已经搜索过,并且找不到多少东西。如果有人知道任何教程/博客甚至理论描述都会有很大的帮助。
关于FRC处理所有问题的建议还有另一件事,我没有完全理解,我是否需要为每个视图控制器放置一个FRC?还有别的办法吗?
答案 0 :(得分:2)
你不应该失去任何东西。 NSFetchedResultsController上的委托将在任何时候更新某些内容时告诉您。如果您有可见的UI,那么您的UI将会更新。如果您没有可见的UI,或者不需要可用的UI,您仍然可以将该FRC链接到您的特定NSManagedObject子类以获取运行状况详细信息,然后根据更改的事实采取任何适当的操作。
根据您的工作情况,可能与实施controllerDidChangeContent(_:)
如果这不能解决您的问题,您将不得不提供有关具体问题的详细信息。
答案 1 :(得分:2)
你提到改变“ViewControllers”,所以我假设当你按照你在评论“List> Health> Activity> Settings”中所说的推动时,每个都是UIViewController
类,对吧?如果是这样,请在每个方法中实现viewWillAppear
方法,并确保在那里进行所有UI初始化。通过这样做,您可以保证当弹出窗口发生时,将调用此方法并更新您的UI(b / c您现在在此方法中具有逻辑以进行更新)。我曾经在viewDidLoad
中进行UI初始化,但遇到了与您现在遇到的问题相同的问题。在我的情况下,将其移至viewWillAppear
是解决方案。
在此之后,如果您仍未在UI中看到正确的值,请在viewWillAppear
方法中放置断点并检查模型中的数据。也许模型不正确 - 在这种情况下,也许你会进行查询(搜索)以再次提取你需要的东西。除非您使用父/子上下文并且未将子上下文更改提交到父上下文,否则此不应该成为问题。
但我觉得它非常笨拙,处理了很多通知。是个 唯一的方法或任何更好的方法存在紧密耦合 个人核心数据模型到UI。
老实说,我不认为有更好的模型,因为你没有在其他视图上使用FRC。如果你没有使用表视图重新加载或获取新数据,那么你绝对不需要使用FRC(尽管我不会说你不应该因为我不能坚定地支持这一点。)
我在我的应用程序中使用这个确切的模型,它有几个不同的视图,通过观察者接收通知 - 与你的工作方式相同。如果效果不佳,还有另外一个选择。
答案 2 :(得分:2)
抱歉,我没有足够的声誉来添加评论。
我会加入其他建议使用FRC的人。我无法帮助您使用博客/教程,但CoreStore ObjectMonitor是一个非常好的示例,因为它可以在不同的(非tableview)上下文中使用。我确定你得到它不会有问题。
答案 3 :(得分:2)
因此,您已经有一个问题的解决方案,使用通知。这没有明显的错误。可以通过仅观察您感兴趣的ID感知来改进它,以防止多个VC处理并检查通知是否适用于它们。这是一个可用的解决方案。
FRC易于使用基于表格/网格的布局,但并不是所有它都有用,因为它提供了特定的上下文观察。在最高级别,这意味着仅响应controllerDidChangeContent:
委托回调来更新UI。这通常比你的通知更好,因为它具体,虽然它在内存消耗方面要贵一点(这是非常小的,无关紧要)。
如果您的详细VC显示多条信息,那么您可能没有使用表/集合视图,但仍然存在列表/网格样式布局,FRC索引路径可能意味着与此相关的内容。
尚未讨论过的替代方案是KVO,它由所有托管对象本机支持。这是最合适的解决方案,因为您正在传递对象,因此您不需要进行任何更高级别/上下文观察。直接使用KVO有时会有点痛苦,所以你想使用一些帮助库,比如this one,所以你可以使用块来处理特定更新的项目。
使用KVO可以获得数据绑定,因此对底层模型数据的更新会直接反映在您的UI上,这是因为详细的观察回调。
答案 4 :(得分:1)
首先,我理解您对使用一对一模式的担忧。 (仅适用于协议:它不是一对一的模式,因为委托可以是许多委托类的委托。实际上会发生这种情况。)
to-many模式确实是通知:它是广播。但我不明白,为什么你有这么多通知?只需听取上下文NSManagedObjectContextDidSaveNotification
,它将为您提供已更改对象的列表。细节视图控制器应该很容易获取它显示的对象。
我误解了你吗?