ios - 如何通过 ViewControllers 管理和释放内存

标签 ios swift memory

我面临一个大问题,我找不到解决方案的唯一原因是因为我缺乏关于 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/

相关文章:

ios - GameplayKit-[GKGraph dealloc] : crash on iOS9. 2

ios - UIImage 性能 : imageNamed vs UIGraphicsGetImageFromCurrentImageContext from bezierPath

进程或库的多个副本之间的 C 字符串文字存储

java - 包含不同类型对象的 ArrayList 是否使用不同数量的内存?

ruby - 此代码是否在 Ruby 中创建循环内存引用?

iphone - 更改了 Xcode 中的目标名称现在它运行黑屏

ios - 在应用程序启动时呈现不同的 UIViewController

objective-c - JS TileMap iOS 8 和快速、难以理解的存档?

ios - 尝试从结构访问 JSON 数据时出现索引超出范围错误

swift - 如何制作通用的序列过滤器包装器?过滤器包含 Set 和 Array 类型的相同 block