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
andEnum
The reason is that in reference type only there may be a situation where multiple objects may refer to the same object.ARC仅适用于引用类型(即
class
,不适用于值类型(例如struct
和Enum
原因是仅在引用类型中,可能存在多个对象可能引用同一对象的情况。
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](https://miro.medium.com/max/9999/1*MBXGWh6KruK3_AqPCerC4w.png)
The User
class has an initializer method that sets the values for name
and id
properties 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
类具有一个初始化程序方法,该方法设置name
和id
属性的值,并打印一条消息以指示初始化已完成。 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](https://miro.medium.com/max/9999/1*6UXOjWS3rnC-IAC8GTL2Sg.png)
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](https://miro.medium.com/max/9999/1*Tmr8fQzb2BtImtHKkKmkXA.png)
We need to assign nil to all three objects to deinitialize the User class instance.
我们需要将nil分配给所有三个对象以取消初始化User类实例。
![Image for post](https://miro.medium.com/max/9999/1*VNd96Mm4y-eNzu53SqH5_Q.png)
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](https://miro.medium.com/max/9999/1*_hNCIsAfiEuKmn7aSkXT3g.png)
强大的参考周期 (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.
在即将到来的示例中,将以创建强大参考周期的方式定义两个类(称为Person
和Application
,它们对签署用户列表的Application组进行建模。
![Image for post](https://miro.medium.com/max/9999/1*qU6bH09aCfEJQnf4gyDcOg.png)
![Image for post](https://miro.medium.com/max/9999/1*mDTwBLWYJzEJgeT30IE5Vg.png)
Next, add the following line and run in your playground.
接下来,添加以下行并在您的操场上运行。
![Image for post](https://miro.medium.com/max/9999/1*rPFduGLrwP3-nnrhIrBMJA.png)
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.
现在,添加musicApplication
到kevinTheUser.app
和kevinTheUser
到musicApplication.user.
![Image for post](https://miro.medium.com/max/9999/1*VFdJLZ1g7zSX3gNxqKIhog.png)
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.
现在运行代码,您将在调试控制台中看到只有kevinTheUser
和musicApplication
没有按预期解除分配。 因为在这两个对象之间形成了很强的参考循环(如下图所示) ,这阻止了ARC履行职责。
![Image for post](https://miro.medium.com/max/9999/1*PFGKzaPxOX60QXrq8DPd_w.png)
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 theApplication
class asweak
现在,我们需要做一些更改来打破周期,方法是将
Application
类中的user
属性指定为weak
![Image for post](https://miro.medium.com/max/9999/1*iXpWYXhjc6BzSHrm-UNoqA.png)
So the Strong Reference Cycle will be broken as shown in the below figure.
因此,强参考循环将被打破,如下图所示。
![Image for post](https://miro.medium.com/max/9999/1*caeJjiN5OyXAO7tiJmlUKA.png)
Now, the ARC will work as expected.
现在,ARC将按预期工作。
![Image for post](https://miro.medium.com/max/9999/1*t5JevwcQbTnfhIuBWOGJqg.png)
Next with another example, we can see how
unowned
contributed to breaking the Strong Reference Cycle. Now consider another class calledSubcription
which holds the information like name, id, isActive, and user details.接下来是另一个示例,我们可以看到
unowned
如何有助于打破“强参考周期”。 现在考虑另一个称为“Subcription
类 其中包含诸如名称,id,isActive和用户详细信息之类的信息。
![Image for post](https://miro.medium.com/max/9999/1*XGkyKvwJIhuxZfL6AIfctg.png)
![Image for post](https://miro.medium.com/max/9999/1*FHN5j8xflraprMgHTXJHnw.png)
![Image for post](https://miro.medium.com/max/9999/1*AFRGQNHBEEhs745vEsSRGQ.png)
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](https://miro.medium.com/max/9999/1*hdai1Da9Ql3YqS4lECNZtQ.png)
![Image for post](https://miro.medium.com/max/9999/1*IQgzu8gjPhoY_0kjp9Ju2w.png)
![Image for post](https://miro.medium.com/max/9999/1*AUHdvxAriFO6F5E-qGHbaQ.png)
![Image for post](https://miro.medium.com/max/9999/1*AUHdvxAriFO6F5E-qGHbaQ.png)
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](https://miro.medium.com/max/9999/1*cczl8BMjSZXge4cybMD8PA.png)
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的基本概念已经很清楚,例如它是如何通过对象之间的强关系形成的,以及如何使用weak
和unowned
来解决参考周期。 在下一节中,我们将了解在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 .someProperty
或self .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 details
of 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.
此属性引用将name
和id
组合为单个字符串的闭包。
![Image for post](https://miro.medium.com/max/9999/1*kd-Dj8HhO1mBxr7cZ_opXw.png)
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](https://miro.medium.com/max/9999/1*FzrvEMV8sxceQplSoDBe-w.png)
![Image for post](https://miro.medium.com/max/9999/1*pFxKgzDr0YMMYW2dtCZxuw.png)
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](https://miro.medium.com/max/9999/1*d2wPjUCOsV60wfOcFEx6ZQ.png)
[unowned self] in the
capture list
[unowned self] in the
捕获列表中包含
[unowned self] in the
打破强参考周期
![Image for post](https://miro.medium.com/max/9999/1*Ucfovgi_FfAmW0o90uVEEQ.png)
[weak self] in the
capture list
[weak self] in the
捕获列表中包含
[weak self] in the
打破强参考周期
![Image for post](https://miro.medium.com/max/9999/1*3uWTK34wIHU5vupLPqd1gg.png)
So the User class is now redefined to eliminate the Strong Reference Cycle.
因此,现在重新定义了User类以消除“强引用周期”。
![Image for post](https://miro.medium.com/max/9999/1*bGNunw13gfjFvWdTFZmwQQ.png)
Now run the playground to witness the breaking the Strong Reference Cycle
现在,在操场上奔跑,见证突破的强参考周期
![Image for post](https://miro.medium.com/max/9999/1*m7ELiN4FYjPfhXma70FYdQ.png)
Source: Apple Docs and sources from Internet
资料来源: Apple Docs和Internet来源
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内存管理