我面临一个大问题,我找不到解决方案的唯一原因是因为我缺乏关于 swift 和 swift 内存管理的知识。所以这是我的担忧。我正在使用 swift 4.0 和 iOS 9.3
我实际上正在制作一个带有登录/注销功能的图片库应用程序。基本应用。 我在 cleanSwift 工作,所以我没有那些巨大的 ViewControllers。
我的应用程序在 3 个 VC 中是分开的:登录名、图库和设置(包含注销)。
这是我的问题。当我注销时,我想创建一个新的 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_
那么我哪里错了,为什么??
谢谢你的回答。
编辑:我有两个问题:
- 我的 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
最佳答案
要从内存中删除 viewController
,您只需将其从导航堆栈中删除即可。因此,当您调用 navigationController?.popViewController(animated: true)
并返回到之前的 View Controller 时,您已经销毁了该 Controller 。
然后,
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 进行任何更改,因为这需要一些时间并且不需要“从内存中删除 Controller ”。如何检查 View Controller 是否完全从导航堆栈中删除?只需在 deinit
函数中编写 print
语句,编译代码并从该 View Controller 返回。
deinit {
print("ViewController deinit")
}
如果此 print
工作正常(您可以在 xcode 控制台中看到文本),您将获得结果 - Controller 已从导航堆栈中删除,但如果没有 print
结果你可能忘记正确管理你的闭包。例如
worker.cleanMemory(completionHandler: { (Value) in
...
})
当您认为 Controller 已经被释放时,这个闭包可能会保留您的 Controller ,这意味着您的 Controller 存在于内存中的某个地方。为了防止这些retain cycles
,你需要使用[weak self]
的[unowned 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
操作之后,没有任何东西可以让您的 Controller 保持事件状态。
这些是编写良好托管代码时应遵循的简单规则。
关于ios - 如何通过 ViewControllers 管理和释放内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48096757/