I find myself constantly worrying about retain cycles when writing code. I think this is just as common as any other problem. I don't know about you, but I hear things like "When do I use the weak keyword? What the heck is this 'unowned' thing?" all the time. The problem we find ourselves in is that we know we need to use the strong, weak, and unowned specifiers to avoid retain cycles in our Swift code, but we don't quite know which one to use. Luckily, I know what they are and when to use them! Hopefully this post will teach you when and where to use these 3 specifiers. Let’s get started ARC ARC is a compile time feature of Apple's version of automatic memory management. The full name is Automatic Reference Counting. It means that for an object, the memory occupied by the object will be reclaimed only when there is no strong reference pointing to it. STRONG - strong reference Let's start with what a strong reference is. It is essentially a normal reference (a pointer or something with the same meaning), but it is special in that it can protect the object from being reclaimed by ARC by increasing the retain count of the object pointed to by the reference by 1. In fact, as long as there is a strong reference to the object from anything, the object will not be reclaimed. Remember this, it will be used later when talking about strong reference cycles and related things.
The example is a linear relationship hierarchy. Kraken has a strong reference to the Tentacle instance, which in turn has a strong reference to the Sucker instance. The reference relationship flows from the parent level (Kraken) down to the child level (Sucker).
Because animateWithDuration is a static method of UIView, the closure here is the parent level and self is the child level. WEAK AND UNOWNED REFERENCES WEAK - Weak Reference A weak reference is a pointer that cannot protect the object it refers to from being reclaimed by ARC. A strong reference can increase the retain count of its object by 1, but a weak reference cannot.
Because tentacle is a let constant. Let cannot be changed at runtime due to specification restrictions. Because weak reference variables (weak variables) will be changed to nil when there is no strong reference pointing to them, the Swift compiler requires you to declare weak reference variables as var. Here is a great example that demonstrates a strong reference cycle, using the NSNotification API (which is still a relatively new API). Take a look at the following code:
At this point we have a strong reference cycle. You see, closures in Swift are very similar to blocks in Objective-C. If a variable is declared outside a closure, referencing it inside the closure will create another strong reference. The only exception to this is when using value types, such as Ints, Strings, Arrays, and Dictionaries in Swift. Making self weak will not increase the retain count of self, which allows ARC to properly destroy it at the right time.
Why is weak self in square brackets? This looks weird! In Swift, we think of arrays when we see square brackets. Guess what? You can specify multiple captured values in a closure! For example:
Looks like an array, right? Now you know why the captured values are written in square brackets. Well, with what we have learned so far, adding [weak self] to the closure capture list in the notification code above can solve the strong reference cycle problem:
#p# Another place where weak and unowned variables are used is when using protocols to implement delegation between multiple classes, because classes in Swift are reference types. Structs and enums can also follow protocols, but they are value types. If a parent class brings a child class to use delegation, like this:
Then we need to use weak variables. In this case, Tentacle holds a strong reference to Kraken in the form of its own delegate property, and Kraken also has a strong reference to Tentacle in its tentacle property. We solve this by adding a weak specifier before the delegate declaration:
What did you say? It doesn't compile? Well, because non-class protocols cannot be marked as weak.
When not to use :class? Apple's documentation says:
Basically, if the reference hierarchy of your own code is the same as what I wrote above, you just add :class. For the case of using structures or enumerations, :class is not needed, because structures and enumerations are value types, and classes are reference types. UNOWNED Weak references and unowned references are essentially the same thing. Unowned references do not increase the retain count of the object they reference. However, the additional advantage of unowned references in Swift is that they are non-optional. This makes it more convenient to use without having to introduce optional binding. This is no different from Implicity Unwrapped Optionals.
You know the answer: just like with implicit optional types, if you can ensure that the reference is not nil when it is used, use unowned. If you are not sure, use a weak reference.
In the example above, the closure captures self as a strong reference, and self also retains a strong reference to the closure through its own closure property, which creates a strong reference cycle. Simply adding [unowned self] to the closure can break this cycle:
Because we call the closure immediately after initializing the RetainCycle class, we can assume that self will no longer be nil. in conclusion Strong reference cycles are bad. But if you write your code carefully, think about your reference hierarchy, and use weak and unowned references appropriately, you can avoid memory leaks and memory abandonment. I hope this article will help you. |
<<: From the perspective of player needs, how can RPG mobile games design excellent social systems?
>>: Do you really understand real-time computing?
How much does it cost to be an agent of Linxia Ch...
Recently, the Indian Space Research Organization ...
How to plan the selling points of a product and m...
"I started to transfer the Cainiao Express S...
Recently, the sand dollar has become a hot topic ...
In the past two years, Xu Huaizhe and Liu Xiong h...
Many people have had this experience: after eatin...
When paddling hard, don't forget to look up a...
In winter, bundles of sugar cane are often seen i...
On my first day at work in 2019, I was assigned n...
Old project replay automatic hanging platform, si...
SATA Express is a new interface standard that intr...
Everyone has drunk cow's milk, goat's mil...
Since the release of iPhone 6s/6s Plus, rumors ab...
On March 13, 2022, Shenzhen issued the "Noti...