[iOS翻译]6分钟内完成iOS内存管理

99 阅读7分钟

在老好的Objective-C中,你应该知道什么是ARC?

原文地址:medium.com/flawless-ap…

原文作者:

发布时间:2019年7月4日 - 6分钟阅读

image.png

最近几天,我在iOS中搜索了更多关于内存管理的内容。对我来说,这是个很难理解的Swift话题。因此,我决定在老好的Objective-C中再深入一点--因为我已经在学习它了,要更多的了解内存管理,深入了解这个话题。比如,在ARC之前是怎么样的?在它之后发生了什么?还有ARC和Garbage Collector的区别是什么......等等。

绪论

当你开始使用对象时,你会发现一个有趣的事情。

对象比整数和浮点数等原始类型对内存的要求更高。无论这些对象是来自于你自己的类,还是来自于你从Apple框架中的类中创建的对象,这一点都是正确的。

幸运的是,我们不必担心手动处理内存地址和手动分配或重新分配内存区域(这对某些语言来说仍然是真实的)。相反,在Objective-C中,我们使用了一种叫做引用计数的东西。

引用计数是什么意思?

当你的应用程序启动时,一个内存区域成为你的对象的可用区域。所以你创建了一个对象,并且为该对象申请了一个内存区域。现在,持有该对象的变量是一个指向该对象的指针。确切地说,是指向一个内存区域的指针。下面发生的事情是,当对象被创建时,它被赋予了所谓的保留计数或引用计数,它代表了一个特定对象的所有者数量。因此,我们可以把它想象成一个,如下图所示。

image.png

调用var的变量是一个指向内存块的指针。所以,在你的程序中,只要你愿意,你就可以用这个指针工作,并对它调用方法。但是当你到达代码块的末端时。这个变量不再是程序的任何部分都能到达或访问的。保留计数又变成了零,因为现在没有任何东西指向那个内存块了。而当保留计数变为零时,运行时引擎就会说,这里有一个没有人关心的内存块。因此,它会释放这个内存块,让它可以被其他对象使用。

可能会出什么问题呢?

这里唯一的问题可能是在你创建对象并将它们从一个地方传递到另一个地方的情况下。所以不清楚指针是否还在范围内。而直到2011年--当ARC(自动引用计数)被添加时,你必须写出关于何时使用完该对象的语句。

在ARC之前

在ARC被添加到Objective-C之前,我们必须要做这样的事情。

MyClass *myObject = [[MyClass alloc] init];
[myObject myMethod]; // call methods
... // doing some stuff with the object
[myObject release]; // releasing the object

我们会写一点代码来创建一个对象。它将被创建。我们会调用该对象的方法。但在某些时候,我们必须明确地调用一个释放声明。而这将是负责采取保留计数下来的。

这对于少量的对象来说不是问题。但是当你有成百上千的对象被创建、操作、用作参数、从一个对象传到另一个对象时... 你必须跟踪它们。如果你把一个对象从程序的一个区域传递到另一个区域,你可能甚至不确定是否可以释放它。或者程序的其他部分是否会负责释放它,甚至可能在你完成它之前就释放了。所以你也可以写出所谓的,保留对该对象的调用。但你仍然需要为任何保留调用匹配一个额外的释放调用。

基本上,在ARC之前,你必须设想你的应用程序将经历的每一个可能的场景-逻辑,以确保你的所有对象的寿命被正确管理。没那么容易。

ARC之后

幸运的是,当使用ARC时,你不再需要使用release autorelease retain调用。但重要的是要了解不正确编写这段代码的危险性。

你可能遇到的问题之一是你可能太快释放。你会创建一个对象,有一个指向那个内存区域的指针,你会调用方法,在某些时候你会释放它。但是如果你仍然有一个有效的指针,那么实际上没有什么可以阻止你写另一行代码来使用它。这将被称为悬空指针。指针存在,但它所指向的东西在内存中不再有效,这可能会导致崩溃。

反过来说,你可能根本不会释放,你可能会创建一个对象。开始调用该对象的方法,然后就任由指针退出作用域而消失。但是你从来没有释放过这个对象,所以你就开始索取越来越多的内存,这就是所谓的内存泄漏。

所以要写很多这样的代码肯定是非常容易出现错误和问题的。现在你可能会想,如果我们使用的是这个新的ARC功能,为什么我还要提到释放和保留调用这种东西的存在。因为释放和保留调用的概念并没有消失,语言仍然会做引用计数。

语言并没有改变。不同的是你根本不需要写保留和释放以及自动释放的调用,因为编译器已经写了。ARC是利用编译器已经变得非常好的事实,任何时候你构建你的项目,编译器,在这种情况下,llvm,也就是Xcode在幕后使用的东西,能够确定你的代码的所有可能路径。它基本上是通过你的代码来合成你所需要的写、保留、释放和自动释放调用。

编译器所做的实际上是在写同样的代码,如果你真的,真的,真的很擅长写内存管理代码的话,你会自己写。 ARC并没有实际改变你的源代码文件,但这实际上是编译器在做什么,当你编译一个项目时,你正在使用ARC。

垃圾回收器和ARC的区别

ARC与拥有垃圾收集器的效果截然不同。使用垃圾收集器的语言通常是所谓的非确定性的。这意味着你无法准确判断对象何时被回收,因为它是由运行时的外部进程管理的。ARC让我们可以做到完全的确定性。代码控制这些对象何时被释放。只是释放它们的代码已经被编译器写好了,而不是由你来写。事实上,当你使用ARC时,不仅你不写这些调用,你也不能写这些调用。如果你试图做哪怕是简单的释放调用,你都会得到一个错误。

结束语

你需要知道保留或释放的想法。它仍然是下面的事情,但是,如果你没有做过,当然要庆幸你不用再做这些事情了。 我很想听听你对这个话题的更多看法,为了更好地理解内存管理这样的话题,你对回到Objective-C这样的语言有什么看法?你之前有做过这样的事情吗?


www.deepl.com 翻译