转换到释放内存后关闭ViewController

时间:2016-09-23 12:56:45

标签: ios swift uiviewcontroller dismiss

我希望释放我的ViewController在解除它后使用的内存。我使用以下代码来呈现新的ViewController并解除旧的ViewController:

let sB: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let newVC: UIViewController = sB.instantiateViewController(withIdentifier: "MyVC")
self.present(newVC, animated: true, completion: { x in
    oldVC.dismiss(animated: false, completion: { _ in //oldVC: variable keeping track of currently visible view controller
        print("done")
    })
})

此代码成功显示newVC并在解除done后打印oldVC。但是,我的记忆仍然保持在屏幕上oldVC时的记忆力 我做错了什么?

FYI

  • 我正在使用ENSwiftSideMenu
    • 由于我没有以不同的方式使用它,所有的ViewControllers都是ENSideMenuNavigationController的子类
  • 我收到有关未在窗口层次结构中的分离视图和视图的控制台警告
  • 对于所有ViewControllers,presentingViewControllerpresentedViewController均为nil

4 个答案:

答案 0 :(得分:4)

检查以下问题:

  1. 您应该在呈现新的ViewController之前解除旧的ViewController,否则您将同时关闭新的ViewController。
  2. 使用ARC快速管理内存。 oldVC未发布,因为某些对象具有强引用权。举个例子,我有一个带有变量tableView的ViewController。当ViewController发布时,tableView将会释放。但同时如果将它链接到另一个未发布的ViewController,则尽管先前的ViewController已发布,但tableView不会发布。
  3. <强>解决方案:

    1. 提供UINavigationController并使用setViewControllers来管理ViewControllers的转换。
    2. 删除oldVC
    3. 的无用引用

      如果你真的不明白。你可以搜索:

      1. ARC
      2. UIViewController过渡

答案 1 :(得分:3)

您的oldVC将不会被取消分配,因为您的newVC(以及任何UIViewController)默认保留对其presentingViewController的强引用 - 显示它的控制器。如果不是这种情况,您将永远无法在不打扰视图层次结构的情况下安全地关闭newVC

就您的具体问题而言,为了解除分配您的旧视图控制器,我建议先解除oldVC,然后在堆栈前面的另一个ViewController中显示您的newVC(可以是UIApplication shared().keyWindow?.rootViewController

答案 2 :(得分:3)

我对UINavigationController的推/弹有同样的问题。 @spassas对于强引用是正确的,这是您newVC未被释放的原因。您应该仔细查看newVC

在我的情况下(用Objective-C编写),有另一个视图控制器被引用作为推送视图控制器的私有属性(你的newVC):

EventActionSheetViewController* actionSheet;

actionSheet对推送的视图控制器(newVC)有强烈的引用作为其委托:

@property (nonatomic) id<EventActionSheetDelegate> delegate;

我一直在检查我的应用程序的内存,发现推送的视图控制器在被导航控制器弹出后没有被释放。几个小时后,我将强引用改为弱,并且结果很明显:

@property (nonatomic, weak) id<EventActionSheetDelegate> delegate;

问题是我推送的视图控制器及其EvenetActionSheetViewController对彼此有很强的引用,并且不知何故没有让对方解除分配。

我建议您检查newVC是否有类似的强引用循环,并尽可能将它们更改为弱。在Swift中使用weak letweak var代替let/var。希望这可以帮助您找到错误。

答案 3 :(得分:1)

尝试使用以下代码替换您的代码:

    let appDel = UIApplication.shared.delegate as! AppDelegate
    let sB: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
    let newVC = sB.instantiateViewController(withIdentifier: "MyVC")
    appDel.window?.rootViewController = newVC
    appDel.window?.makeKeyAndVisible()

希望这有效!

编辑: 您还可以通过将以下代码添加到所有视图控制器来检查旧的View Controller是否已被取消初始化:

    deinit {
        debugPrint("Name_Of_View_Controller deinitialized...")
    }

编辑2:

如果要保留视图控制器中的演示流程,并且只想关闭最后一个视图控制器,即

在过渡期间:masterVC - &gt; oldVC - &gt; NEWVC

从oldVC过渡到newVC后,你想返回masterVC,释放oldVC的内存。 您可以将masterVC引用传递给oldVC并实现您想要的内容:

if(masterVC != nil) {
         oldVC.dismiss(animated: false, completion: {
            let sB: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
            let newVC = sB.instantiateViewController(withIdentifier: "vc2")
            self.masterVC!.present(newVC, animated: false, completion: {
                print("done")
            })
        })
}

这适用于你陈述的情况。