大约一周以来,我一直在强调这个问题,试图找出缓慢但稳定的 Apple Watch 应用程序性能下降的根源。在大约两天的时间里,我的应用程序的 UI 会变得越来越迟钝。我已将其缩小为复杂更新代码。即使我将并发症更新减少到绝对最低限度,这个问题仍然会发生,尽管比使用一些实际数据更新并发症要慢。我每 10 分钟更新一次并发症。一旦新数据到来,我只需执行
for (CLKComplication *comp in [CLKComplicationServer sharedInstance].activeComplications) {
[[CLKComplicationServer sharedInstance] reloadTimelineForComplication:comp];
}
这反过来又调用:
- (void)getCurrentTimelineEntryForComplication:(CLKComplication *)complication withHandler:(void(^)(CLKComplicationTimelineEntry * __nullable))handler {
...
}
这工作正常,新数据显示,但是当重复几十次时,主应用程序的 UI 响应开始显着下降,并且当它重复大约一百次时(这发生在不到一天的时间,更新时间为 10 分钟)用户界面确实显着变慢。
我对复杂结构没有什么特别的想法——没有时间旅行,只显示当前数据,一切都为此做好了准备。为了确保我没有看错地方,我做了一个每秒重新加载时间线的测试,在这个测试中,我的 getCurrentTimelineEntryForComplication 看起来像这样:
- (void)getCurrentTimelineEntryForComplication:(CLKComplication *)complication withHandler:(void(^)(CLKComplicationTimelineEntry * __nullable))handler {
handler(nil);
}
所以那里实际上什么都没有,只需将空处理程序发回即可。然而,即使在这种情况下,在大约一百次时间线重新加载后,主应用程序的 UI 也会明显变慢。
其他一些需要注意的事项:
如果我不更新复杂功能,应用程序的 UI 性能永远不会降低,无论我打开它多少次,或者我使用它多久,或者数据获取代码在后台运行多少次。
在模拟器中对此进行测试时,我无法让性能下降,但我可以始终看到来自并发症更新的小而稳定的内存泄漏(同样,无论我在内部进行多么简单的更新,都会发生这种情况getCurrentTimelineEntryForComplication 方法。
有没有其他人注意到这一点,有没有希望处理它?难道我做错了什么?目前,我确保仅在数据发生变化时更新并发症,但这只会推迟问题,而不是解决问题。
10月24日编辑
我在真正的手表上做了更仔细的测试,虽然之前由于某种原因我没有注意到与真正手表相关的内存泄漏,但我现在肯定看到它发生了。真实设备完全反映了在模拟器上看到的问题,只是使用了不同的初始内存分配量。
同样,我所做的只是在一个常量循环上调用 reloadTimelineForComplication,并使用来自缓存数据对象的单行文本更新复杂性,否则复杂性控制器将被剥离到最低限度。当复杂功能从表盘上移除时,内存泄漏可以预见地停止。
我的主要项目是用ObjectiveC编写的,但是我用一个用Swift制作的测试项目重复了测试,没有任何区别。此外,最新的 XCode 8.1 GM 和随模拟器提供的 watchOS 3.1 beta 以及在安装了 watchOS3.1 的真实手表上运行时,问题仍然存在。
2017 年 1 月 24 日 编辑
可悲的是,这个问题在 watchOS 3.1.3 中仍然存在,完全没有改变。与此同时,我联系了 Apple 的代码级支持,向他们发送了示例代码,他们确认问题存在,并告诉我提交错误报告。大约两个月前我确实提交了一份错误报告,但直到现在它仍然是未分类的,我猜这意味着还没有人看过它。
2017 年 1 月 31 日 编辑
Apple 已经在 watchOS3.2 beta 1 中解决了这个问题。我一直在模拟器和真实手表上测试它。一切都很好,没有内存泄漏或性能下降了。最后没有解决方法,直到他们决定修复它。