Swiftpipe理内存

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


我有一些关于内存pipe理的问题。

我正在构build一个照片编辑应用程序。 所以保持内存使用率低是重要的。 另外我不会发布代码,因为在做一件特定的事情时我没有大的内存泄漏。 发生的一切,我只是失去了几个KB / MB。 而成千上万的代码行来find千字节是没有趣的;)

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

我的第一个看法只是一个tableview,花了我大约5mb的内存。 然后,您拍摄一些照片,应用一些filter,将其保存到核心数据,然后返回到第一个视图。

除了驱动第一个视图所需的数据之外,是否有可能真正摆脱内存中的所有内容? (这非常保存和真棒5MB)

或者即使你把所有东西都设置为零,总会有东西留下来。


奖金问题: UIImageJPEGRepresentationUIImagePNGRepresentation之间的文件大小/ CPU负载有差异吗? 我知道你可以用JPEG方法设置压缩质量(在CPU / GPU上更难?)。

只是想尽一切办法减less内存压力。


更新:

有人指出,这个问题可能太模糊了。

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

  • 在某些情况下,峰值内存使用率过高
  • 导航到第二个视图控制器,并返回导致泄漏
  • 编辑图像会导致内存泄漏。
  • 将filter应用于超过4-5个图像导致内存不足导致崩溃,此时没有更多的内存泄漏。 (在仪器中validation)

这是所有的testing在iPhone 4s,而不是模拟器。

这里有一个meme来点亮这个网站的心情。

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


不同等级的MM:

硬件内存

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

想象一下,我们有一个无限期地在所有线程上运行的函数。 它做一件事,加载一个图像,转换成黑/白,并保存。 所有的图像最大在几个MB的和该function没有创build软件内存泄漏。 由于图像没有设置的大小,并可能有不同的压缩,他们没有相同的足迹。 此function将永远崩溃您的应用程序。

此“硬件”内存泄漏是由于function始终占用下一个可用的内存插槽。

由于没有空闲时间,操作系统不介入“实际清理内存”。 在每个通行证之间延迟完全解决这个问题。


语言特定的MM

铸件

一些操作对记忆没有影响,另一些操作:

 let myInt : Int = 1 Float(myInt) // this creates a new instance 

尝试转换:

 (myInt as Float) // this will not create a new instance. 

引用types与值types| 类与结构

两者都有其优点和危险。

结构是内存密集的,因为它们是值types 。 这意味着它们在分配给另一个实例时复制它们的值,有效地使内存使用率翻倍 。 没有修复/解决这个问题。 这是什么使结构结构。

没有这种行为,因为它们是引用types 。 分配时不会复制。 相反,他们创build另一个参考同一个对象ARC自动引用计数是跟踪这些引用。 每个对象都有一个参考计数器。 每次分配时,它都会增加一个。 每次你设置一个对nil的引用时,封闭函数结束,或者封闭对象消失,计数器就会closures。

当计数器达到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. 

设一个参照weak

 class MyOtherClass { weak var myclass : MyClass? deinit { print("deinit") // gets called } } 

进出

函数捕获传递给它们的值。 但也可以将这些值标记为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 } 

函数式编程

状态是随时间变化的价值

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

更多关于这里

面向对象编程使用具有变化/变异状态的对象。 而不是创build一个新的值,旧的值被更新。

function编程可以使用更多的内存。

在FP上的例子


选配

可选项允许您将事情设置为零。 这将降低类或取消初始化结构的引用计数。 设置为零是清理内存的最简单方法。 这与ARC联手。 一旦你将一个类的所有引用设置为零,它将会退出并释放内存。

如果您没有将实例创build为可选项,则数据将保留在内存中,直到封闭函数结束或封闭类取消为止。 你可能不知道什么时候会发生。 可选项可以让你控制多久的活着。


API MM

许多“内存泄漏”是由具有“清理”function的框架引起的,您可能没有调用它。 一个很好的例子是UIGraphicsEndImageContext()上下文将留在内存中,直到这个函数被调用。 当创build上下文的函数结束时,或者当涉及的映像设置为nil时,它不会清除。

另一个很好的例子是closuresViewControllers。 把一个VC放到一个VC然后再继续下去也许是有意义的,但是这个segue实际上会创build一个VC。 后退不会破坏风险投资。 调用dismissViewControllerAnimated()将其从内存中删除。

阅读课程参考,并仔细检查没有“清理”function。


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

在这里输入图像说明

点击Xcode右上angular的应用程序名称。

在这里输入图像说明

点击popup菜单中的“编辑scheme”。

在这里输入图像说明

确保左侧select了“运行”,然后单击窗口顶部附近的诊断选项卡。

在“内存pipe理”标题下,勾选“启用Guard Malloc”

你可能也想尝试检查“logging”头下的“分布式对象”和“malloc栈”

更多的信息在后卫malloc,卫兵边缘和涂鸦可以在这里find。

希望这可以帮助!