Swift. ARC

class Person {
public let name: String
init(name: String) {
self.name = name
print("person is initialized")
}
deinit {
print("person is reinitialized")
}
}
var person1: Person?
var person2: Person?
var person3: Person?
person1 = Person(name: "Maxim")
// person is initialized
// retain(Person(Maxim)), 1 strong reference
person2 = person1
// retain(Person(Maxim)), 2 strong references
person3 = person1
// retain(Person(Maxim)), 3 strong references
person1 = nil
// release(Person(Maxim)), 2 strong references
person2 = nil
// release(Person(Maxim)), 1 strong reference
person3 = nil
// release(Person(Maxim)), 0 strong references
// person is deinitialized

Autorelease Pool

// some function bodyfor _ in 0..<10 {
autoreleasepool {
// UIImage inherits NSObject (Objective-C)
let image = UIImage(contentsOfFile: "image.jpg") // heavy
}
}

Strong Reference Cycles Between Class Instances

// Problemclass Person {
let name: String
init(name: String) { self.name = name }
var apartment: Apartment? // strong reference
deinit { print("person is deinitialized") }
}
// An apartment may not always have a tenant
class Apartment {
let unit: String
init(unit: String) { self.unit = unit }
var tenant: Person? // strong reference
deinit { print("apartment is deinitialized") }
}
var person: Person?
var apartment: Apartment?
person = Person(name: "Maxim")
apartment = Apartment(unit: "1408")
person!.apartment = apartment // the person refers to the apartment
apartment!.person = person // the apartment refers to the person
person = nil
apartment = nil
// no deinit called
// resources will be never deallocated
// Solution (using weak)class Person {
let name: String
init(name: String) { self.name = name }
var apartment: Apartment? // strong reference
deinit { print("person is deinitialized") }
}
// An apartment may not always have tenant
// Tenant lifetime is shorter than apartment one
class Apartment {
let unit: String
init(unit: String) { self.unit = unit }
weak
var tenant: Person?
deinit { print("apartment is deinitialized") }
}
var person: Person?
var apartment: Apartment?
person = Person(name: "Maxim")
apartment = Apartment(unit: "1408")
person!.apartment = apartment // the person refers to apartment
apartment!.person = person // the apartment refers to person
person = nil
apartment = nil
// the person is deinitialized
// the apartment is deinitialized
// resources are deallocated
// Solution (using unowned)class Person {
let name: String
init(name: String) { self.name = name }
var card: CreditCard?
deinit { print("person is deinitialized") }
}
// A credit card must always have customer
// A customer lifetime is the same as credit card one
class CreditCard {
let number: Int
unowned let customer: Person
init(number: Int, customer: Person) {
self.number = number
self.customer = customer
}
deinit { print("card is reinitialized") }
}
var person: Person?person = Person(name: "Maxim")
person!.card = CreditCard(number: 12345, customer: person!)
person = nil
// the person is deinitialized
// the card is deinitialized
// resources are deallocated
weak var person = Person()
unowned var card = CreditCard()

Strong Reference Cycles for Closures

// Problemclass 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("element is deinitialized")
}
}
var element: HTMLElement? = HTMLElement(
name: "p", text: "something"
)
print(element?.asHTML ?? "")
element = nil
// no deinit called
// resources will be never deallocated
// ... [unowned self, weak delegate = self.delegate, someVariable]
// Solutionclass HTMLElement {
let name: String
let text: String?
lazy var asHTML: () -> String = { [weak 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("element is deinitialized")
}
}
var element: HTMLElement? = HTMLElement(
name: "p", text: "something"
)
print(element?.asHTML ?? "")
element = nil
// the element is deinitialized
// resources are deallocated

Resources

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store