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. When each time you use 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. The output of the above program execution is as follows: In the above example, ARC will track your newly created 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. An example of inadvertently generating loop strong references is shown below. The example defines two classes: 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 The output of the above program execution is as follows: The output of the above program execution is as follows: 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 The following example shows you when a closure references the Instance of 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. 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 If the captured reference is never set to Front The output of the above program execution is as follows: 9.40.1. ARC function #
init()
method to create a new instance of a class, ARC allocates a large chunk of memory to store the instance’s information. 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
Runoob initialization begins
Runoob is deconstructed
9.40.3. Cyclic strong references between class instances #
Person
the number of references to the instance, and will be found in the
Person
destroy the instance when it is no longer needed. 9.40.4. Example #
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 #
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
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
ARC
The student's score is 98
9.40.8. Loop strong reference caused by closure #
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 #
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)</\(self.name)>"
} 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.
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. 9.40.10. Weak reference and non-primary reference #
nil
defines the capture within the closure as a weak reference.
nil
a headless reference should be used instead of a weak reference 9.40.11. Example #
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)</\(self.name)>"
} 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
<p>hello, world</p>
p is deconstructed