迅捷管理记忆

R M*_*nke 25 memory-management ios automatic-ref-counting swift

这个问题已经清理完毕,重要的信息转移到下面的答案.


我对内存管理有一些疑问.

我正在构建一个照片编辑应用程序.因此,保持低内存使用率非常重要.此外,我不会发布代码,因为在执行某项特定操作时我没有大量内存泄漏.我只是丢失了几个KB/MB的所有发生的事情.通过成千上万行代码来查找千字节并不好玩;)

我的应用程序使用核心数据,许多cifilter东西,位置和基础知识.

我的第一个视图只是一个tableview,花了我大约5mb的内存.然后你拍摄一些照片,应用一些过滤器,这会保存到核心数据然后你回到第一个视图.

除了驱动第一个视图所需的数据之外,是否有可能真正摆脱内存中的所有内容.(非常节省和令人敬畏的5mb)

或者即使你把所有东西都设为零,总会留下一些东西?


奖金问题:UIImageJPEGRepresentation和 之间的文件大小/ CPU负载是否存在差异UIImagePNGRepresentation?我知道你可以用JPEG方法设置压缩质量(在cpu/gpu上更难?).

只是尽可能地减少记忆压力.


更新:

有人向我指出,这个问题可能过于含糊.

我在某些时候遇到的问题如下:

  • 在某些时候,峰值内存使用率太高
  • 导航到第二个视图控制器并返回导致泄漏
  • 编辑图像会导致内存泄漏.
  • 将过滤器应用于4-5个以上的图像会因内存不足而导致崩溃,此时不再有内存泄漏.(在文书中核实)

这些都是在iPhone 4s上测试的,而不是模拟器.

这里有一个模因来减轻这个网站的情绪.

R M*_*nke 33

这个问题已经开放了很长时间,我现在有足够的信心回答它.


不同级别的MM:

硬件内存

在Swift with ARC中,我们无法清理实际的硬件RAM.我们只能让操作系统为我们做到这一点.一部分是使用正确的代码(optionalsweak),另一部分是为操作系统创造时间来完成它的工作.

想象一下,我们有一个无限期地在所有线程上运行的函数.它做了一件事,加载图像,转换为黑/白并保存.所有图像最多只有几个mb,并且该功能不会产生软件内存泄漏.由于图像没有设置大小并且可能具有不同的压缩,因此它们没有相同的占用空间.此功能将始终使您的应用程序崩溃.

此"硬件"内存泄漏是由始终占用下一个可用内存插槽的功能引起的.

操作系统不介入"实际清理内存",因为没有空闲时间.在每次传递之间设置延迟完全解决了这个问题.


特定语言的MM

铸件

某些操作对内存没有影响,其他操作则:

let myInt : Int = 1
Float(myInt) // this creates a new instance
Run Code Online (Sandbox Code Playgroud)

尝试投射:

(myInt as Float) // this will not create a new instance.
Run Code Online (Sandbox Code Playgroud)

参考类型与值类型| 类与结构

两者都有其优点和危险.

结构是内存密集型的,因为它们是值类型.这意味着它们复制时分配给另一个实例,有效它们的值加倍的内存使用情况.没有解决方法/解决此问题.这就是Structs Structs的作用.

没有此行为,因为它们是引用类型.分配时不会复制.相反,他们创建对同一对象的另一个引用.ARC自动引用计数是跟踪这些引用的内容.每个对象都有一个引用计数器.每次分配时,它都会增加一个.每次设置对nil的引用,封闭的函数结束,或者封闭的对象取消,计数器就会关闭.

当计数器达到0时,对象被取消初始化.

有一种方法可以防止实例取消初始化,从而造成泄漏.这称为强参考周期.

弱者的好解释

class MyClass {

    var otherClass : MyOtherClass?

    deinit {
        print("deinit") // never gets called
    }
}

class MyOtherClass {

    var myclass : MyClass?

    deinit {
        print("deinit") // never gets called
    }
}

var classA : MyClass? = MyClass()

// sorry about the force unwrapping, don't do it like this
classA!.otherClass = MyOtherClass()
classA!.otherClass!.myclass = classA // this looks silly but in some form this happens a lot

classA = nil
// neither the MyClass nor the MyOtherClass deinitialised and we no longer have a reference we can acces. Immortalitiy reached they have.
Run Code Online (Sandbox Code Playgroud)

设置一个引用 weak

class MyOtherClass {

    weak var myclass : MyClass?

    deinit {
        print("deinit") // gets called
    }
}
Run Code Online (Sandbox Code Playgroud)

进出

函数捕获传递给它们的值.但也可以将这些值标记为inout.这允许您更改传递给函数的Struct而无需复制Struct.这可能会节省内存,具体取决于您传递的内容以及您在函数中执行的操作.

它也是一种不使用元组而具有多个返回值的好方法.

var myInt : Int = 0

// return with inout
func inoutTest(inout number: Int) {

    number += 5

}

inoutTest(&myInt)
print(myInt) // prints 5

// basic function with return creates a new instance which takes up it's own memory space
func addTest(number:Int) -> Int {

    return number + 5

}
Run Code Online (Sandbox Code Playgroud)

功能编程

国家是时间的价值

函数式编程是面向对象编程的反向部分.函数式编程使用不可变状态.

更多关于这里

面向对象编程使用具有更改/变异状态的对象.旧值不会更新,而是创建新值.

功能编程可以使用更多内存.

FP上的例子


选配

可选项允许您将事物设置为零.这将降低Classes或deinitialise Structs的引用计数.将事物设置为nil是清理内存的最简单方法.这与ARC携手并进.一旦将Class的所有引用设置为nil,它将会释放并释放内存.

如果不创建实例作为可选项,则数据将保留在内存中,直到封闭函数结束或封闭类取消.您可能不知道何时会发生这种情况.可选项可让您控制多长时间保持活动状态.


API MM

许多"内存泄漏"是由具有"清理"功能的框架引起的,您可能没有调用它.一个很好的例子是UIGraphicsEndImageContext()在调用此函数之前,Context将保留在内存中.当创建上下文的函数结束或涉及的图像设置为nil时,它不会清除.

另一个很好的例子是解雇ViewControllers.切换到一个VC然后向后移动可能是有意义的,但segue实际上创建了一个VC.segue back不会破坏VC.要求dismissViewControllerAnimated()将其从内存中删除.

阅读课程参考并仔细检查没有"清理"功能.


如果您确实需要仪器查找泄漏,请查看此问题的其他答案.

  • @Sulthan再次检查了一切.我将关于函数式编程的部分简化为基本思想,并添加了更多信息的链接.函数式编程确实倾向于使用更多内存.当我开始编程时我问了这个问题并且它非常广泛:"如何快速释放内存以及如何防止使用太多内存".这个答案涵盖了大多数.如果你贬低并说它是错误的,请提供消息来源.答案的很大一部分首先作为更新包含在问题中.7个赞成票可能是人们发现它有用和正确的结果.最近我把它移到了这个答案. (3认同)
  • @Sulthan,我想要的只是在需要时改进答案,所以我认真询问哪些部分是错误/误导的。我并不固执,犯了错误也能接受。您能否提供更多反馈,而不仅仅是投反对票和留下负面评论? (2认同)

Mor*_*ode 6

在此输入图像描述

点击Xcode右上角的应用名称.

在此输入图像描述

点击弹出菜单中的"编辑方案".

在此输入图像描述

确保在左侧选择"RUN",然后单击窗口顶部附近的诊断选项卡.

在'内存管理'标题下检查'启用Guard Malloc'

您可能还想尝试检查'logging'标题下的'distributed objects'和'malloc stack'

有关防护malloc,防护边缘和涂鸦的更多信息可以在这里找到.



希望这可以帮助!