9.40. Swift automatic reference count (ARC)

发布时间 : 2025-10-25 13:33:46 UTC      

Page Views: 9 views

Swift uses automatic reference counting (ARC) to track and manage application memory

Usually we don’t need to free memory manually because ARC automatically frees up memory when an instance of a class is no longer in use.

But sometimes we still need to implement memory management in our code.

9.40.1. ARC function #

  • When each time you use init() method to create a new instance of a class, ARC allocates a large chunk of memory to store the instance’s information.

  • The memory contains the type information of the instance, as well as the values of all related properties of the instance.

  • When the instance is no longer in use, ARC frees up the memory occupied by the instance and allows the freed memory to be diverted to other uses.

  • To ensure that instances in use are not destroyed, ARC tracks and calculates how many properties, constants, and variables each instance is being referenced.

  • Instance is assigned to a property, constant, or variable, all of which create a strong reference to the instance, and the instance is not allowed to be destroyed as long as the strong reference is there.

9.40.2. ARC instance #

class Person { let name: String init(name: String) { self.name = name print("\(name) Start initialization") } deinit { print("\(name) Deconstructed") } } // The value will be automatically initialized to nil and will not be referenced to an instance of the Person class yet var reference1: Person? var reference2: Person? var reference3: Person? // Create a new instance of the Person class reference1 = Person(name: "Runoob") //Assign values to the other two variables, and this instance will have two additional strong references reference2 = reference1 reference3 = reference1 //Break the first strong reference Reference1=nil //Break the second strong reference Reference2=nil //Break the third strong reference and call the destructor function Reference3=nil 

The output of the above program execution is as follows:

Runoob initialization begins Runoob is deconstructed 

9.40.3. Cyclic strong references between class instances #

In the above example, ARC will track your newly created Person the number of references to the instance, and will be found in the Person destroy the instance when it is no longer needed.

However, we might write code that a class will never have 0 strong references. This happens when two class instances maintain a strong reference to each other and keep each other from being destroyed. This is the so-called cyclic strong reference.

9.40.4. Example #

An example of inadvertently generating loop strong references is shown below. The example defines two classes: Person and Apartment to model the apartment and its residents:

class Person { let name: String init(name: String) { self.name = name } var apartment: Apartment? deinit { print("\(name) is deconstructed") } } class Apartment { let number: Int init(number: Int) { self.number = number } var tenant: Person? deinit { print("Apartment #\(number) is deconstructed") } } //Both variables are initialized to nil Var runoob: Person? Var number73: Apartment? //Assignment Runoob=Person (name: "Runoob") Number73=Apartment (number: 73) //The exclamation mark is used to expand and access instances in the optional variables runoob and number73 //Circular strong reference created Runoob Apartment=number73 Number73 Tenant=runoob //When breaking the strong references held by runoob and number73 variables, the reference count does not drop to 0, and the instance is not destroyed by ARC //Note that when you set these two variables to nil, none of the destructors are called. //The strong reference loop prevents the destruction of instances of the Person and Apartment classes, and causes a memory leak in your application Runoob=nil Number73=nil 

9.40.5. Resolve cyclic strong references between instances #

Swift provides two ways to solve the loop strong reference problem you encounter when using the properties of a class:

  • Weak reference

  • No master reference

Weak references and unowned references allow one instance of a circular reference to reference another instance without maintaining a strong reference. In this way, instances can refer to each other without generatingcircular strong references.

For the lifecycle to become nil uses weak references for an instance ofthe on the contrary, after initializing the assignment, it is no longer assigned to nil , using no primary reference

9.40.6. Weak reference instance #

class Module { let name: String init(name: String) { self.name = name } var sub: SubModule? deinit { print("\(name) main module") } } class SubModule { let number: Int init(number: Int) { self.number = number } weak var topic: Module? deinit { print("The number of sub module topics is \(number)") } } var toc: Module? var list: SubModule? toc = Module(name: "ARC") list = SubModule(number: 4) toc!.sub = list list!.topic = toc toc = nil list = nil 

The output of the above program execution is as follows:

ARC main module The number of sub module topics is 4 

9.40.7. No primary reference instance #

class Student { let name: String var section: Marks? init(name: String) { self.name = name } deinit { print("\(name)") } } class Marks { let marks: Int unowned let stname: Student init(marks: Int, stname: Student) { self.marks = marks self.stname = stname } deinit { print("The student's score is \(marks)") } } var module: Student? module = Student(name: "ARC") module!.section = Marks(marks: 98, stname: module!) module = nil 

The output of the above program execution is as follows:

ARC The student's score is 98 

9.40.8. Loop strong reference caused by closure #

A circular strong reference also occurs when you assign a closure to a property of a class instance, and the instance is used in the closure body. Some property of the instance may be accessed in this closure, such as self.someProperty or a method of the instance is called in the closure, such as self.someMethod . In both cases, the closure “captures” the self, resulting in a circular strong reference.

9.40.9. Example #

The following example shows you when a closure references the self . How to generate a loop strong reference after. An example is defined called HTMLElement , represented by a simple model HTML a single element:

class HTMLElement { let name: String let text: String? lazy var asHTML: () -> String = { if let text = self.text { return "<\(self.name)>\(text)" } else { return "<\(self.name) />" } } init(name: String, text: String? = nil) { self.name = name self.text = text } deinit { print("\(name) is being deinitialized") } } // Create an instance and print information var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world") print(paragraph!.asHTML()) 

HTMLElement class produces class instances and asHTML a loop strongreference between the closures of the default.

Instance of asHTML property holds a strong reference to the closure. However, the closure uses self (referenced by the self.name and self.text so the closure captures the self , which means that the closure in turn holds the HTMLElement a strong reference to the instance. In this way, the two objects produce a circular strong reference.

Solve the loop strong reference caused by the closure: define the capture list as part of the closure when defining the closure, which can solve the loop strong reference between the closure and the class instance.

9.40.10. Weak reference and non-primary reference #

When closures and captured instances always refer to each other and are always destroyed at the same time, the capture within the closure is definedas an unowned reference.

Conversely, when a reference is captured, it may sometimes be nil defines the capture within the closure as a weak reference.

If the captured reference is never set to nil a headless reference should be used instead of a weak reference

9.40.11. Example #

Front HTMLElement in the example, no master reference is the correct way to solve the problem of circular strong reference. Write like this HTMLElement class to avoid circular strong references:

class HTMLElement { let name: String let text: String? lazy var asHTML: () -> String = { [unowned self] in if let text = self.text { return "<\(self.name)>\(text)" } else { return "<\(self.name) />" } } init(name: String, text: String? = nil) { self.name = name self.text = text } deinit { print("\(name) is deconstructed") } } //Create and print HTMLElement instances var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world") print(paragraph!.asHTML()) // The HTMLElement instance will be destroyed and the message printed by its destructor will be visible paragraph = nil 

The output of the above program execution is as follows:

<p>hello, worldp> p is deconstructed      
                
                
            
        
        
《地理信息系统原理、技术与方法》  97

最近几年来,地理信息系统无论是在理论上还是应用上都处在一个飞速发展的阶段。 GIS被应用于多个领域的建模和决策支持,如城市管理、区划、环境整治等等,地理信息成为信息时代重要的组成部分之一; “数字地球”概念的提出,更进一步推动了作为其技术支撑的GIS的发展。 与此同时,一些学者致力于相关的理论研究,如空间感知、空间数据误差、空间关系的形式化等等。 这恰好说明了地理信息系统作为应用技术和学科的两个方面,并且这两个方面构成了相互促进的发展过程。