如何通过ViewControllers管理和释放内存 [英] How can I manage and free memory through ViewControllers
问题描述
我面临着一个大问题,而我无法找到解决方案的唯一原因是因为我对swift和内存管理缺乏了解。所以这是我的担忧。我在swift 4.0和iOS 9.3中工作
I'm in front of a big issues, and the only reason I can't find a solution is because my lack of knowledge about swift and memory management in swift. So here is my concerns. I'm working in swift 4.0 and iOS 9.3
我实际上正在制作一个带登录/注销的图片库应用程序。基本申请。
我在cleanSwift工作所以我没有那些巨大的ViewControllers。
I'm actually making a picture gallery app with login/logout. Basic application. I'm working in cleanSwift So I don't have those HUGE ViewControllers.
我的应用程序在3 VC中分开:登录,图库和设置(包含LogOut)。
My application is separate in 3 VC : The login, the gallery and the settings (which contains the LogOut).
这是我的问题。当我退出时,我想创建一个新的loginVC并清除所有以前的VC。
所以我有我的cleanMemory函数,它将所有UIImage设置为nil
Here is my problem. When I log out, I want to create a new loginVC and clear all previous VC. So I have my cleanMemory function which set all the UIImage to 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的休息符
and then I delete the rests of the UIImage and the 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次时,我的应用程序崩溃,因为我管理不好我的内存_
But when I create my new LoginVC.. my RAM didn't decrease.. And when I check the app memory, not a single VC was deleted.. And when I execute the loop Logout/Login 3 times, my app crash because I'm not well managing my RAM_
那我哪里出错了,为什么?
So where did I get wrong, and why ??
谢谢你的回答。
编辑:我有2个问题:
- 我的completionHandler保留了我的VC live
- 我用.present切换VC,这样就把我的VC留在了内存中。
所以你应该像这样改变VC:
So you should change VC like that :
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let destinationVC = storyboard.instantiateViewController(withIdentifier: "LoginController")
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.window?.rootViewController = destinationVC
推荐答案
<要从内存中删除 viewController
,您只需将其从导航堆栈中删除即可。因此,当您调用 navigationController?.popViewController(animated:true)
并返回上一个视图控制器时,您已经销毁了该控制器。
To remove viewController
from memory you simply need to remove it from navigation stack. So when you call navigationController?.popViewController(animated: true)
and back to previous view controller you already destroy that controller.
然后,
这是我的问题。当我退出时,我想创建一个新的loginVC并清除所有以前的VC。所以我有我的cleanMemory函数,在注销时将所有UIImage设置为nil
Here is my problem. When I log out, I want to create a new loginVC and clear all previous VC. So I have my cleanMemory function which set all the UIImage to nil
这是停止所有请求的好习惯,但是你没有需要对UI进行任何更改,因为它需要一些时间而且不需要从内存中删除控制器。如何检查视图控制器是否完全从导航堆栈中删除?只需在 deinit
func中编写 print
语句,编译代码并从此视图控制器返回。
on logout it's good practice to stop all request but you don't need to do any changes to UI, because it takes some time and it doesn't need to "remove controller from memory". How to check if view controller completely removed from navigation stack? Simply write print
statement in deinit
func, compile code and go back from this view controller.
deinit {
print("ViewController deinit")
}
如果这个 print
工作正常(你可以在xcode控制台中看到文字),你就可以实现结果 - 控制器有已从导航堆栈中删除,但如果没有 print
结果,您可能忘记正确管理您的闭包。例如
If this print
works fine (you can see text in xcode console), you achieve the result - controller has been removed from navigation stack, but if there is no print
result you probably forget to right manage your closures. For example
worker.cleanMemory(completionHandler: { (Value) in
...
})
当您认为控制器已经解除分配时,此关闭可能会占用您的控制器,这意味着您的控制器存在于某处在记忆中。要防止这些保留周期
,您需要使用 [无主自我]
[弱自我]
(只是谷歌这个关键字,这很容易理解)像这样:
this closure may hold your controller when your think that controller already deallocated and it means that your controller present somewhere in memory. To prevent these retain cycles
you need to use [unowned self]
of [weak self]
(just google for this keywords, it's very easy to understand) like this:
// or you can use `[unowned self]`
worker.cleanMemory(completionHandler: { [weak self] (Value) in
guard let `self` = self else { return } // only for `weak` way
...
})
因此,在这种情况下有在从导航堆栈中弹出
操作之后,没有任何东西可以让你的控制器保持活着状态。
这些是编写管理良好的代码时应遵循的简单规则。
So, in this case there are nothing that can hold your controller alive after pop from navigation stack
action or so.
These are simple rules that you should follow to write well managed code.
这篇关于如何通过ViewControllers管理和释放内存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!