【问题标题】:How can I manage and free memory through ViewControllers如何通过 ViewControllers 管理和释放内存
【发布时间】:2018-01-04 13:52:29
【问题描述】:

我面临一个大问题,我找不到解决方案的唯一原因是我缺乏关于 swift 和 swift 内存管理的知识。所以这是我的担忧。我正在使用 swift 4.0 和 iOS 9.3

我实际上正在制作一个带有登录/注销的图片库应用程序。基础应用。 我在 cleanSwift 中工作,所以我没有那些巨大的 ViewControllers。

我的应用程序在 3 个 VC 中是独立的:登录、图库和设置(其中包含 LogOut)。

这是我的问题。当我注销时,我想创建一个新的 loginVC 并清除所有以前的 VC。 所以我有我的 cleanMemory 函数,它将所有 UIImage 设置为 nil

func cleanMemory(request: Gallery.Request) { // Interactor
    worker.cleanMemory(completionHandler: { (Value) in

        self.interventions?.removeAll() // Interventions contains UIImages
        self.interventionsSelected.removeAll() // InterventionsSelected contains UIImages

    })

}

然后我删除 UIImage 和 VC 的其余部分

func cleanMemory() {

    interactor?.cleanMemory(request: Gallery.Request())
    self.displayedInterventions.removeAll() // displayedInterventions contains UIImages
    interactor = nil
    router = nil
    self.removeFromParentViewController()
    self.navigationController?.popViewController(animated: true)
}

但是当我创建我的新 LoginVC.. 我的 RAM 没有减少.. 当我检查应用程序内存时,没有一个 VC 被删除.. 当我执行循环注销/登录 3 次时,我的应用程序崩溃,因为我没有很好地管理我的 RAM_

那么我哪里错了,为什么??

感谢您的回答。

编辑:我遇到了 2 个问题:

  • 我的 completionHandler 让我的 VC 保持活力
  • 我正在用 .present 切换 VC,以便将我的 VC 保留在内存中。

所以你应该这样改变VC:

let storyboard = UIStoryboard(name: "Main", bundle: nil)
let destinationVC = storyboard.instantiateViewController(withIdentifier: "LoginController")
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.window?.rootViewController = destinationVC

【问题讨论】:

  • 当用户点击 SettingsVC 中的 Logout 时,如何再次返回 LoginVC?
  • 也许你有一个保留周期?
  • 绝对是@ZaidPathan。我有一个注销按钮,我创建了一个新的 LoginVC,我将我的 loginVC 设置为应用程序的根目录并切换到它。
  • 我认为我没有保留周期@Francis.Beauchamp。我所有的 VC 链接都很薄弱。我的问题更多是关于在这些情况下内存和“空闲”内存是如何工作的
  • 您可能想看看 Instruments,它可以帮助您找到内存问题。这是一个关于它的教程的链接。 raywenderlich.com/166125/…

标签: ios swift memory


【解决方案1】:

要从内存中删除viewController,您只需将其从导航堆栈中删除即可。因此,当您调用 navigationController?.popViewController(animated: true) 并返回之前的视图控制器时,您已经销毁了该控制器。

那么,

这是我的问题。当我注销时,我想创建一个新的 loginVC 并清除所有以前的 VC。所以我有我的 cleanMemory 函数,它将所有 UIImage 设置为 nil

注销时最好停止所有请求,但您不需要对 UI 进行任何更改,因为这需要一些时间并且不需要“从内存中删除控制器”。如何检查视图控制器是否完全从导航堆栈中删除?只需在deinit func 中编写print 语句,编译代码并从该视图控制器返回。

deinit {
    print("ViewController deinit")
}

如果print 工作正常(您可以在 xcode 控制台中看到文本),您将获得结果 - 控制器已从导航堆栈中删除,但如果没有 print 结果,您可能忘记正确管理您的闭包.例如

worker.cleanMemory(completionHandler: { (Value) in
    ...
})

当您认为控制器已被释放时,此闭包可能会保留您的控制器,这意味着您的控制器存在于内存中的某个位置。要防止这些retain cycles,您需要使用[unowned self] 的[weak self](这个关键字只需google,很容易理解),如下所示:

// or you can use `[unowned self]`
worker.cleanMemory(completionHandler: { [weak self] (Value) in
    guard let `self` = self else { return } // only for `weak` way
    ...
})

因此,在这种情况下,在 pop from navigation stack 左右操作之后,没有什么可以让您的控制器保持活动状态。 这些是编写管理良好的代码时应遵循的简单规则。

【讨论】:

  • 哦。我得到它。这很有意义。我没有考虑维护 VC 存在的 completionHandler。我遇到了另一个问题,我的路由中有保留周期,我正在存储 VC 并使用“.show”进行切换。这也是有道理的,我修复了它并通过更改为 root 来更改我的路由。再次感谢您,我将编辑并关闭我的帖子! :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-10-06
  • 2016-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-10
  • 1970-01-01
相关资源
最近更新 更多