swift内存管理_Swift的ARC中的内存管理

swift内存管理

Memory Management is the programming discipline of managing the object’s life cycles and release them when it is not needed. Managing object memory is a key for the app performance i.e., if an app doesn’t free unneeded objects, its performance will be compromised.

内存管理是用于管理对象生命周期并在不需要时释放它们的编程准则。 管理对象内存是提高应用程序性能的关键,即,如果应用程序不释放不需要的对象,则其性能将受到损害。

You’ll level up your Memory Management skills with the following topics:

您将通过以下主题来提高您的内存管理技能:

  • ARC — explained in a short description.

    ARC —简短说明中进行了说明。
  • How ARC is working.? with an example.

    ARC是如何工作的? 举个例子。
  • What is a Strong Reference Cycle.?

    什么是强参考周期?
  • Break the cycle by weak and unowned reference with an example.

    举一个例子,以弱者和无主的引用打破循环。
  • Choosing weak and unowned reference to break the cycle.

    选择弱的和无用的参考来打破周期。
  • Strong Reference Cycles in Closures.

    封闭的强大参考周期。

ARC —自动参考计数 (ARC — Automatic Reference Counting)

  • ARC is a compiler feature that provides automatic memory management of objects.

    ARC是一种编译器功能,可提供对象的自动内存管理。
  • Before ARC, a developer needs to deallocate the objects which are no longer needed by inserting the code wherever needs.

    在ARC之前,开发人员需要通过在任何需要的地方插入代码来释放不再需要的对象。
  • ARC works by adding code at compile time to ensure that objects live as long as necessary, but no longer. That is it will start counting the number of references to each object. When the reference count drops to zero then the object memory is released.

    ARC的工作方式是在编译时添加代码,以确保对象的生存时间尽可能长,但不再存在。 即它将开始计算对每个对象的引用数。 当参考计数降至零时,则释放对象存储器。
  • ARC will keep track of objects and it automatically releases the objects which are no longer needs.

    ARC将跟踪对象,并自动释放不再需要的对象。
  • ARC will work only for the reference type i.e., class and not for value types i.e., struct and Enum The reason is that in reference type only there may be a situation where multiple objects may refer to the same object.

    ARC仅适用于引用类型(即class ,不适用于值类型(例如structEnum 原因是仅在引用类型中,可能存在多个对象可能引用同一对象的情况。

As a develpoer, we don’t need to care about object management, but you need to know the relationships between objects in your application.

作为开发人员,我们不需要关心对象管理,但是您需要了解应用程序中对象之间的关系。

ARC —工作原理? (ARC — How it works?)

  • ARC allocates a memory every time you create a new instance of a class which includes the details about the type of the instance and the stored property values associated with the instance.

    每次创建类的新实例时,ARC都会分配一个内存,其中包括有关实例类型的详细信息以及与该实例相关联的存储属性值。
  • Since ARC holds the information about the object, it can able to free its memory. But if the object is released which is still in use, then the application may end up with a crash if you tried to access the instance.

    由于ARC保留有关对象的信息,因此它可以释放其内存。 但是,如果释放了仍在使用的对象,那么如果您尝试访问该实例,则应用程序可能会崩溃。
  • To overcome this scenario, ARC tracks the properties that are currently referred to all the instances of the class. So it will not release the memory of the object until the existence of at least one active reference to the instance.

    为了克服这种情况,ARC会跟踪当前引用到该类的所有实例的属性。 因此,在至少存在一个对实例的有效引用之前,它不会释放对象的内存。
  • To make this solution as a possible one, we need to assign a class instance to any property as a strong reference to the instance. Therefore, ARC holds the instance so tightly and it won’t deallocate the instance until the strong reference remains.

    为了使该解决方案成为可能,我们需要将一个类实例分配给任何属性,以作为对该实例的强引用。 因此,ARC如此紧密地保存实例,并且在保留强引用之前,它不会取消分配实例。
  • Special care should be taken to achieve the above-mentioned solution. Because in some cases it will lead to Strong Reference Cycles between the class instance. If the cycle formed then the ARC will not work.

    为了实现上述解决方案,应格外小心。 因为在某些情况下,它将导致类实例之间的强引用循环。 如果形成循环,则ARC将无法正常工作。

Let us see how ARC works with an example. GitHub

让我们看一下ARC是如何工作的。 的GitHub

Image for post

The User class has an initializer method that sets the values for name and idproperties and also prints a message to indicate that initialization has been done. The User class also has a deinitializer that prints a message when all instances of the class are deallocated.

User类具有一个初始化程序方法,该方法设置nameid属性的值,并打印一条消息以指示初始化已完成。 User类还具有一个反初始化器,该类在取消分配该类的所有实例时将显示一条消息。

The following code snippet defines three variables of type User?, used to set up multiple references to a new User instance in subsequent code. Next, create a new User instance and assign to one of the instances say user1.

以下代码段定义了三个类型为User?变量User? ,用于在后续代码中设置对新User实例的多个引用。 接下来,创建一个新的User实例,并为其中一个实例分配user1

Image for post

Now in the Debug view, "User kevin with an ID kevin.r@gmail.com is being initailized" is printed confirming that initialization has taken place. To confirm the same declare two more instances of type User? and initialize these two instances with user1

现在,在“调试”视图中,显示"User kevin with an ID kevin.r@gmail.com is being initailized"初始化"User kevin with an ID kevin.r@gmail.com is being initailized"以确认已进行初始化。 为了确认相同,再声明两个User?类型的实例User? 并使用user1初始化这两个实例

Image for post

We need to assign nil to all three objects to deinitialize the User class instance.

我们需要将nil分配给所有三个对象以取消初始化User类实例。

Image for post

From the above example, it is clear that the ARC won’t deallocate the User instance until all three instances are broken.

从上面的示例中可以清楚地看到,直到所有三个实例都被破坏,ARC才会取消分配User实例。

Now, add a CoreFoundation function CFGetRetainCount(_:) to show case the role of reference count in ARC.

现在,添加一个CoreFoundation函数CFGetRetainCount(_ :)来展示ARC中引用计数的作用。

Image for post

强大的参考周期 (Strong Reference Cycle)

Even though ARC will take care of object management, we need to take care of the relation between objects. If you are not able to map the relations between the objects properly, then in some cases where an instance of a class never gets deinitialized. This will happen if two class instances hold a strong reference to each other and this scenario is termed as Strong Reference Cycle.

即使ARC将负责对象管理,我们也需要注意对象之间的关系。 如果无法正确映射对象之间的关系,则在某些情况下,永远不会取消初始化类的实例。 如果两个类实例相互拥有强引用,并且这种情况称为强引用周期,就会发生这种情况。

In the upcoming example, two classes called Person and Application which models the group of Applications signed up the list of Users will be defined in such a way that to create a strong reference cycle.

在即将到来的示例中,将以创建强大参考周期的方式定义两个类(称为PersonApplication ,它们对签署用户列表的Application组进行建模。

Image for post
User class with a strong app object
具有强大应用对象的用户类别
Image for post
Application class with a strong user object
具有强大用户对象的应用程序类

Next, add the following line and run in your playground.

接下来,添加以下行并在您的操场上运行。

Image for post

So far so good as both the objects are initialized and deinitialized (as the object will survive only within the scope) so then the memory is recycled.

到目前为止,这两个对象都已初始化和取消初始化(因为该对象将仅在范围内存在),因此可以回收内存。

Now, add musicApplication to kevinTheUser.app and kevinTheUser to musicApplication.user.

现在,添加musicApplicationkevinTheUser.appkevinTheUsermusicApplication.user.

Image for post
Swift code to show the Swift代码显示 Strong Reference Cycle 强大的参考周期

Now run the code, and you’ll see in the debug console that only kevinTheUser and musicApplication do not deallocate as expected. Because a strong reference cycle has been formed between these two objects (as shown in the image below) that prevent ARC to do his job.

现在运行代码,您将在调试控制台中看到只有kevinTheUsermusicApplication没有按预期解除分配。 因为在这两个对象之间形成了很强的参考循环(如下图所示) ,这阻止了ARC履行职责。

Image for post
Strong Reference Cycle 强参考周期”

Breaking this Strong Reference Cycle can be done by specifying the relationship between reference objects either by weak or unowned references. Because it won’t increase the reference count of an object.

乙 reaking此斯特朗基准周期可以通过指定由无主的引用之间的参考对象的任一关系来完成。 因为它不会增加对象的引用计数。

  • Now, we need to do some changes to break the cycle by specifying the user property in the Application class as weak

    现在,我们需要做一些更改来打破周期,方法是将Application类中的user属性指定为weak

Image for post
Application class with a 弱用户对象的 weak user object 应用程序

So the Strong Reference Cycle will be broken as shown in the below figure.

因此,强参考循环将被打破,如下图所示。

Image for post
breaking the cycle 打破循环后,对象之间关系的可视化表示

Now, the ARC will work as expected.

现在,ARC将按预期工作。

Image for post
Swift code to show the breaking of Strong Reference Cycle
Swift代码显示 强参考周期 突破
  • Next with another example, we can see how unowned contributed to breaking the Strong Reference Cycle. Now consider another class called Subcription which holds the information like name, id, isActive, and user details.

    接下来是另一个示例,我们可以看到unowned如何有助于打破“强参考周期”。 现在考虑另一个称为“ Subcription 其中包含诸如名称,id,isActive和用户详细信息之类的信息。

Image for post
Subscription class with a Strong 用户对象的 user object 订阅
Image for post
Strong Reference Cycle 强参考周期”
Image for post
Swift code to show the Swift代码显示 Strong Reference Cycle 强大的参考周期

In the above example, it is clearly inferred that a Strong Reference Cycle is formed as shown in the above visual Representation. Now, make the user as unowned in Subscription class to break the cycle as shown in the below code and the same has been visually represented.

在上面的示例中,可以清楚地推断出,如上述视觉表示中所示,形成了一个强参考循环。 现在,让user 作为unowned Subscription 类以中断循环,如下面的代码所示,并且已在视觉上表示出来。

Image for post
unowned user object 拥有用户对象的订阅类
Image for post
breaking the cycle 打破循环后,对象之间关系的可视化表示
Image for post
Visual representation of the relation between the objects after breaking the cycle
打破循环后,对象之间关系的可视化表示
Image for post
breaking the 突破Strong Reference Cycle 强参考周期

Since the Strong Reference Cycle has been broken, both the objects get deallocated once it is out of scope as shown in the below code.

由于强引用循环已中断,因此一旦超出范围,两个对象将被释放,如下面的代码所示。

选择弱的和无用的参考来打破循环。 (Choosing weak and unowned reference to break the cycle.)

Image for post

Weak reference when the other instance has a shorter lifetime and it should be declared as variables of an optional type and it gets automatically becomes nil when the referenced object goes away. In simple words, weak can be used where two properties, both of which are allowed to be nil. In the above example, for an Application class, it is not mandatory to get the User details, because signup is not mandatory for all applications.

当其他实例有一个较短的寿命,它应该被声明为可选类型的变量,它会自动获取变得W¯¯EAK参考 nil引用对象消失。 简而言之,在两个属性都允许nil. ,可以使用函数nil. 在上面的示例中,对于Application类,获取用户详细信息不是强制性的,因为并不是所有应用程序都必须注册。

In simple words, weak can be used where two properties, both of which are allowed to be nil. In the above example, for an Application class, it is not mandatory to get the User details, because signup is not mandatory for all applications.

简而言之,在两个属性都nil. ,可以使用函数nil. 在上面的示例中,对于Application类,获取用户详细信息不是强制性的,因为并不是所有应用程序都必须注册。

Unowned reference used when the other instance has the same lifetime or a longer lifetime ant it will accept only non-optional type.

当另一个实例具有相同的生存期或更长的生存期蚂蚁时使用的U 引用 ,它将仅接受非可选类型。

In simple words, unowned used where one property that is allowed to be nil and another property that cannot be nil which has the potential to cause a strong reference cycle. In the above example, the Subscription class has the property user of type User should be a non-optional value. Because subscription should know the details of the user.

简而言之,“ 所有权”用于一个可能nil属性,而另一个不能nil属性可能导致强大的参考周期。 在上面的例子中, 订阅类有类型用户的属性用户应该是一个非可选值。 因为订阅应该知道用户的详细信息。

The use of unowned to break the cycle may cause a problem during run time. For example, If you try to access the value of an unowned reference after that instance has been deallocated, you’ll get a runtime error.

使用unown中断周期可能会在运行时引起问题。 例如,如果您在实例解除分配后尝试访问一个无主引用的值,则会收到运行时错误。

So far, it is cleared about the fundamental concepts of ARC such as how it forms by strong relations between objects and how to resolve Reference Cycle using weak and unowned. In the next section, we going to see how the Strong Reference Cycle is formed inClosures and of course how to break the same cycle.

到目前为止,关于ARC的基本概念已经很清楚,例如它是如何通过对象之间的强关系形成的,以及如何使用weakunowned来解决参考周期。 在下一节中,我们将了解在Closures如何形成强参考周期 当然还有如何打破同样的循环

封闭的强大参考周期 (Strong Reference Cycles in Closures)

In Closure, a Strong Reference Cycle will occur if the closure assigned to a property of a class instance, and the body of that closure captures the instance i.e., class instance and closure are keeping each other alive. For example, if the closure’s body uses self.someProperty or self.someFunction() then it leads to a Strong Reference Cycle.

在闭包中,如果将闭包分配给类实例的属性,并且该闭包的主体捕获该实例,即类实例和闭包彼此保持活动状态,则将发生强引用循环。 例如,如果闭包的主体使用self .somePropertyself .someFunction()则将导致强引用循环。

The below example shows how a strong reference cycle created when using a closure referenced toself. This example defines a class called User In addition to these two simple properties (name & id), the User class defines a lazy property called detailsof type () -> String. This property references a closure that combines name and id into a sing String.

下面的示例显示了使用引用到self.的闭包时如何创建强引用循环self. 本示例定义了一个名为User的类 除了这两个简单属性( name和id )之外, User类还定义了一个懒惰属性,称为type () -> String. details () -> String. 此属性引用将nameid组合为单个字符串的闭包。

Image for post

In the above example, the User class creates a strong reference cycle between an User instance and the closure details. Here’s how the cycle looks like:

在上面的示例中, User类在User实例和闭包details之间创建了一个强大的引用周期。 周期如下所示:

Image for post
Strong Reference Cycle between Class instance and closure 强引用循环的方式
Image for post
Swift code to show the Swift代码显示 Strong Reference Cycle 强大的参考周期

Strong Reference Cycle has been resolved between the class instance and closure by defining a capture list in closure’s definition e.g. [unowned self] or [weak self]. as mentioned below.

通过在闭包的定义中定义捕获列表 ,例如[unowned self]解决了强实例引用在类实例和闭包之间的问题。 [weak self]. 如下所述。

Image for post
Breaking the Strong Reference Cycle by included [unowned self] in the capture list
通过 [unowned self] in the 捕获列表中包含 [unowned self] in the打破强参考周期
Image for post
Breaking the Strong Reference Cycle by included [weak self] in the capture list
通过 [weak self] in the 捕获列表中包含 [weak self] in the打破强参考周期
Image for post
breaking the cycle using 视图来可视化表示 unowned in the Closure’s capture list 打破周期

So the User class is now redefined to eliminate the Strong Reference Cycle.

因此,现在重新定义了User类以消除“强引用周期”。

Image for post
User class after eliminating the Strong Reference Cycle 用户类别

Now run the playground to witness the breaking the Strong Reference Cycle

现在,在操场上奔跑,见证突破的强参考周期

Image for post
Swift code to show the breaking of Strong Reference Cycle
Swift代码显示 强参考周期 打破

Source: Apple Docs and sources from Internet

资料来源: Apple DocsInternet来源

Get the full source code at GitHub

GitHub上 获取完整的源代码

Reach me on LinkedIn

LinkedIn 上到达我

翻译自: https://medium.com/ivymobility-developers/memory-management-in-swift-by-arc-62bf4f0e2ff5

swift内存管理

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值