ios - 在使用转换时替换 UIWindow 的 rootViewController,似乎正在泄漏

标签 ios xcode memory-leaks instruments uipresentationcontroller

环境
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 仍在内存中。

enter image description here

也遇到了这个 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>.

对原始问题或警告消息的任何想法表示赞赏。

更新

我相信我已经将范围缩小到这个缺少版本的保留。

enter image description here

这就是可能的冒犯性调用。

 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/

相关文章:

ios - 添加和删​​除 NSNotificationCenter Observer - UIApplicationDidEnterBackgroundNotification - 正确的方法?

ios - Storyboard的 Swift 输入和事件处理

swift - 子类化自定义 UIViewController 时出现内存泄漏

python - 使用 python 2.7 时内存泄漏

c++ - 使用 make_unique 语句重新分配 unique_ptr 对象 - 内存泄漏?

ios - Swift:加载/库/音频/插件/HAL/NRDAudioClient 时出错:找不到合适的图像

objective-c - Appirater 的 App Store ID 不同于 plist 的 ID,而且显然是随机的

ios - 如何从苹果 api json 创建 .cer

c++ - 这里是否存在资源泄漏/双重释放的可能性?

ios - 从备份还原sqlite文件后如何重置Core Data堆栈?