如何通过 ViewControllers 管理和释放内存
Posted
技术标签:
【中文标题】如何通过 ViewControllers 管理和释放内存【英文标题】:How can I manage and free memory through 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/… 【参考方案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 来更改我的路由。再次感谢您,我将编辑并关闭我的帖子! :)以上是关于如何通过 ViewControllers 管理和释放内存的主要内容,如果未能解决你的问题,请参考以下文章
如何通过 viewControllers 的导航控制器设置自定义 segue 操作
如何从它的项目 ViewControllers 访问 UITabBarController 的变量
无法通过 UINavigationcontroller.viewControllers 更改类的属性
Xcode:如何将对象从一个 viewControllers 视图移动到另一个 viewControllers 视图?
如何从 navigationController(viewControllers/stack) 弹回指定 viewController?