环境
iOS 9.2
Xcode 7.2
我想更换 UIWindow's rootViewController使用动画,同时也将其从 View 层次结构中删除。
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 中首次引入的。
如果这是设计使然,是否有发布源 View Controller 的选项?
使用 UIPresentationController 的子类
override func shouldPresentInFullscreen() -> Bool {
return true
}
override func shouldRemovePresentersView() -> Bool {
return true
}
似乎没有任何区别。无法在 SDK 中找到任何其他内容。
目前我发现的唯一方法是使用 UIViewController,在进行转换之前使用屏幕上当前内容的快照代替 Root View Controller 。
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:]
最佳答案
我记录了那个错误报告; Apple 工程部门对此没有任何回应。
我随错误报告一起提交的示例代码演示了该问题,地址为 https://github.com/adurdin/radr21404408
据我所知,这个问题在当前版本的 iOS 中仍然存在,但我没有进行详尽的测试。谁知道,也许 9.3 beta 修复了它? :)
在我遇到此错误的应用程序中,我们一直在使用自定义转换和 rootViewController 替换大多数屏幕转换。我还没有找到解决此泄漏的方法,并且由于某些原因无法轻松删除所有 rootViewController 操作,因此通过尽量减少我们使用 presentViewController 和 friend 的地方并仔细管理我们需要它的地方来解决这个问题。
我认为有可能避免该错误同时仍保留与 rootViewController 交换类似功能(但尚未实现)的一种方法是让 rootViewController 成为占据全屏的自定义容器 View Controller ,并定义一个演示上下文。我不会交换窗口的 rootViewController,而是交换此容器中的单个 subview Controller 。并且因为容器定义了呈现上下文,所以呈现将从容器而不是被交换的 child 发生。这样应该可以避免泄漏。
关于ios - 在使用转换时替换 UIWindow 的 rootViewController,似乎正在泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34813889/