假设我有一个视图控制器,当点击一个按钮时,我使用自适应弹出窗口显示.现在在某些情况下,我可能想要将目的地视图控制器包含在(例如)导航控制器中.所以,我将自己设置为popoverPresentationController的委托代理,并实现presentationController:viewControllerForAdaptivePresentationStyle:method.
但是我注意到一些奇怪的东西:在某些情况下,对象没有被释放.如果在前面提及的方法中,我将导出的控件中的所显示的视图控件:
func presentationController(controller: UIPresentationController,viewControllerForAdaptivePresentationStyle style: UIModalPresentationStyle) -> UIViewController? { return UINavigationController(rootViewController: controller.presentedViewController) }
在关闭导航控制器被释放,但是所呈现的视图控制器保持分配.
相比之下,如果通过自适应弹出窗口直接显示导航控制器,则关闭导航控制器及其包含的详细信息控制器可以正确解除分配.
为了演示,请参考这个测试项目(Swift):https://github.com/djbe/AdaptivePopoverSegue-Test
在导航控制器中动态包装时,我们得到了什么(点击“Popover,导航自动添加”按钮):
--- Showing details --- Loaded details view controller (0x7fab31632b70) Loaded navigation controller (0x7fab32815600) Deinit navigation controller (0x7fab32815600)
您可以看到,细节视图控制器永远不会被释放.
我查看了presentationController的文档:viewControllerForAdaptivePresentationStyle:但没有具体提及所有权,强大的保留等…
我尝试使用“分配工具”工具,但是在这种(简单)的情况下涉及到很多保留/释放,我无法直接找到问题.
有没有人遇到这个问题?或者你有什么想法如何解决这个问题?
解
由@TomSwift如下所述,由于控制器和segue之间的循环引用,存在一个错误.解决这个问题的唯一方法是将目标控制器包装在导航控制器中,是通过在segue(custom)的init方法中进行包装.
我已经在Github上更新了我的示例代码,以展示如何使用@Vasily所提到的解决方案实现这一点,但仍然允许使用协议进行动态包装行为,而不使用使用NSUserDefaults的恶意解决方法.
解决方法
解
您需要创建自定义的UIStoryboardSegue类并覆盖init函数.
样品:
class StoryboardSegue: UIStoryboardSegue { override init(identifier: String?,source: UIViewController,destination: UIViewController) { super.init(identifier: identifier,source: source,destination: NavigationController(rootViewController: destination)) } }
Main.storyboard
结果