【发布时间】:2016-04-21 05:07:22
【问题描述】:
环境
iOS 9.2
Xcode 7.2
我希望将 UIWindow's rootViewController 替换为动画,同时还将其从视图层次结构中移除。
class FooViewController: UIViewController
{
}
class LeakedViewController: UIViewController
{
}
然后在 AppDelegate 中简单地启动转换
self.window!.rootViewController = LeakedViewController()
let fooViewController = FooViewController()
self.window!.rootViewController?.presentViewController(fooViewController, animated: true){ unowned let window = self.window!
window.rootViewController = fooViewController
}
在 Instruments 中对此进行分析,请注意 rootViewController 仍在内存中。
还遇到了这个bug report,这似乎表明 iOS 8.3 中存在相同的问题并且仍然处于打开状态。
未能找到任何参考资料表明这是
的一部分UIViewController.presentViewController(animated:completion:)
source view controller 被保留(很可能是 UIPresentationController?),或者如果这是一个错误。请注意,UIPresentationController 最初是在 iOS 8 中引入的。
如果这是设计使然,是否有释放源视图控制器的选项?
使用 UIPresentationController 的子类
override func shouldPresentInFullscreen() -> Bool {
return true
}
override func shouldRemovePresentersView() -> Bool {
return true
}
似乎没有任何区别。无法在 SDK 中找到其他任何内容。
目前我发现的唯一方法是在进行转换之前使用 UIViewController 以及当前屏幕上的快照来代替根视图控制器。
let fooViewController = FooViewController()
let view = self.window!.snapshotViewAfterScreenUpdates(false)
let viewController = UIViewController()
viewController.view.addSubview(view)
self.window!.rootViewController = viewController
self.window!.rootViewController?.presentViewController(dashboardViewController!, animated: true){ unowned let window = self.window!
window.rootViewController = fooViewController
}
它确实有效,但在控制台中会出现以下警告
Unbalanced calls to begin/end appearance transitions for <UIViewController: 0x79d991f0>.
对原始问题或警告信息的任何想法表示赞赏。
更新
我相信我已将其范围缩小到缺少版本的保留。
那是可能的冒犯电话。
0 UIKit -[UIPresentationController _presentWithAnimationController:interactionController:target:didEndSelector:]
【问题讨论】:
-
看到完全一样的东西,这让我很头疼……未发布的控制器保留了他们旧的 Core Data 对象/获取的结果控制器并导致崩溃。你有没有想出一个“不错”的解决方案或类似的东西?
-
@Jordan AFAICS,没有单一的解决方案。可能就像我描述的屏幕截图一样简单,丢弃您不需要的视图层次结构(只保留叶子)或根据您的上下文重用/释放内存的方法。
-
我最终编写了一个文件修复程序 - 如果您有兴趣,我可能会分享代码。它是如何工作的:从 UIViewController 的扩展开始,它劫持 viewDidLoad() 以获取对每个活动视图控制器的引用。单例对象使用 KVO 观察窗口的 rootController 属性,在发生任何更改之前,它会向 rootViewController 层次结构中即将泄漏内存的每个控制器发送dismissViewController(animated: false)。
标签: ios xcode memory-leaks instruments uipresentationcontroller