Person ์ด๋ผ๋ class ์ฝ๋๋ก ์ค๋ช ํ๋ค.
class Person {
let name: String
init(name: String) {
self.name = name
print("\(name) is being initialized")
}
deinit {
print("\(name) is being deinitialized")
}
}
Optional ์ ๋ง๋ค๋ฉด nil ์ด ํ ๋น๋์ด, ์์ง ์ฐธ์กฐํ๊ณ ์์ง ์์ ์ํ.
var reference1: Person?
var reference2: Person?
var reference3: Person?
์ค์ Person ์ธ์คํด์ค๋ฅผ ๋ง๋ค์ด ํ ๋นํ๋ ์๊ฐ ๊ฐํ ์ฐธ์กฐ๊ฐ ๋ง๋ค์ด์ง๋ค.
reference1 = Person(name: "John Appleseed")
// Prints "John Appleseed is being initialized"
// ๊ทธ๋ฌ๋ฉด ๋ณ์์ ํ ๋นํ์ง ์๊ณ , ์ด๊ธฐํ ๊ตฌ๋ฌธ๋ง ํธ์ถํด๋ฒ๋ฆฌ๋ฉด ์ด๋ป๊ฒ ๋ ๊น?
Person(name: "DDOSANG")
// ๊ฐํ ์ฐธ์กฐ 2๊ฐ ์ถ๊ฐ. = 3
reference2 = reference1
reference3 = reference1
reference1 = nil // Person ์ธ์คํด์ค์ ๋ํ ๊ฐํ ์ฐธ์กฐ 2
reference2 = nil // Person ์ธ์คํด์ค ๊ฐํ ์ฐธ์กฐ 1
reference3 = nil // ๊ฐํ ์ฐธ์กฐ 0 : ์ด์ Person ์ธ์คํด์ค๋ฅผ ์ฌ์ฉํ์ง ์์. -> ๋ฉ๋ชจ๋ฆฌ ํ ๋น ํด์
// Prints "John Appleseed is being deinitialized"
class Person {
let name: String
init(name: String) { self.name = name }
var apartment: Apartment?
deinit { print("\(name) is being deinitialized") }
}
class Apartment {
let unit: String
init(unit: String) { self.unit = unit }
var tenant: Person?
deinit { print("Apartment \(unit) is being deinitialized") }
}
// ์์ง ๋ฉ๋ชจ๋ฆฌ์ ์ฌ๋ผ๊ฐ์ง ์์.
var john: Person?
var unit4A: Apartment?
// ๋ฉ๋ชจ๋ฆฌ์ ์ฌ๋ผ๊ฐ๊ณ Person, Apartment ์ธ์คํด์ค์ ๊ฐ๊ฐ ์ฐธ์กฐ๊ฐ ์๊น.
// ํ์ฌ ๊ฐ ์ธ์คํด์ค ๋ด์ apartment, tenant ๋ณ์๋ nil ๋ก ํ ๋น๋์ด ์ฐธ์กฐ๋์ง ์์ ์ํ.
john = Person(name: "John Appleseed") // Person ์ฐธ์กฐ 1
unit4A = Apartment(unit: "4A") // Apartment ์ฐธ์กฐ 1
๊ทธ๋ฐ๋ฐ ์ฌ๊ธฐ์ ์๋ก๋ฅผ ์ฐธ์กฐํ๊ฒ ๋๋ค๋ฉด??
john!.apartment = unit4A // Apartment ์ฐธ์กฐ 2
unit4A!.tenant = joh // Person ์ฐธ์กฐ 2
nil ๋ก ๋ณ๊ฒฝํด๋ ์ฐธ์กฐ ์นด์ดํธ๊ฐ 1์ด๊ธฐ ๋๋ฌธ์, ๋์ด์ ์ฐ์ด์ง ์๋๋ฐ๋ ๋ฉ๋ชจ๋ฆฌ์์ ๋ด๋ ค๊ฐ์ง ์๋ ์ํฉ์ด ์จ๋ค.
john = nil // Person ์ฐธ์กฐ 1
unit4A = nil // Apartment ์ฐธ์กฐ 1
weak self
, unowned self
โญ๏ธโญ๏ธnil
๋ก ์๋ ์ ์ธํ๋ค.var
๋ก๋ง ์ ์ธํ ์ ์๋ค.weak var delegate?
class Person {
let name: String
init(name: String) { self.name = name }
var apartment: Apartment?
deinit { print("\(name) is being deinitialized") }
}
class Apartment {
let unit: String
init(unit: String) { self.unit = unit }
// weak var ๋ก ์ ์ธ.
weak var tenant: Person?
deinit { print("Apartment \(unit) is being deinitialized") }
}
var john: Person?
var unit4A: Apartment?
์ํํธ ์ธ์คํด์ค ์ชฝ์์ ์ฝํ ์ฐธ์กฐ๋ฅผ ํ๊ณ ์๋ค.
john = Person(name: "John Appleseed")
unit4A = Apartment(unit: "4A")
john!.apartment = unit4A
unit4A!.tenant = john
๊ฐํ ์ฐธ์กฐ๋ฅผ ํ๊ณ ์๋ Person ์ ๋์ด๋ฒ๋ฆฌ๋ฉด?
์ฝํ ์ฐธ์กฐ๋ฅผ ํ๊ณ ์๋ Apartment ์ tennant ๋ ์๋์ผ๋ก nil ์ด ํ ๋น๋๋ฉฐ ์ฐธ์กฐ๊ฐ ๋์ด์ง๊ฒ ๋๋ค.
john = nil
// Prints "John Appleseed is being deinitialized"
๊ทธ๋ฆฌ๊ณ unit4A ์ฐธ์กฐ๋ ๋์ผ๋ฉด?
unit4A = nil
// Prints "Apartment 4A is being deinitialized"
๋ ๋ค ํ ๋น์ด ํด์ ๋๋ค.
NOTE: ๊ฐ๋น์ง ์ปฌ๋ ์ ์ ์ฌ์ฉํ๋ ์์คํ (ex. js) ์์๋ ๋ฉ๋ชจ๋ฆฌ ์๋ ฅ์ด ๊ฐ๋น์ง ์ฝ๋ ์ ์ ํธ๋ฆฌ๊ฑฐ ํ ๋๋ง ๊ฐํ ์ฐธ์กฐ๊ฐ ์๋ ๊ฐ์ฒด๋ฅผ ๋ฉ๋ชจ๋ฆฌ์์ ๋ด๋ฆฐ๋ค. ๊ทธ๋์ ์บ์ฑ์ weak reference ๋ก ํ์ฉํ๋ ๊ฒฝ์ฐ๊ฐ ์๋๋ฐ,
Swift ๋ ์ฐธ์กฐ ์นด์ดํธ๊ฐ 0์ด ๋์๋ง์ ๋ฉ๋ชจ๋ฆฌ์์ ๋ด๋ ค๋ฒ๋ฆฌ๊ธฐ ๋๋ฌธ์ ์บ์ฑ์ ๊ทธ๋ฐ ๋ฐฉ์์ผ๋ก ๊ตฌํํ๋ค๊ฐ ์บ์ฑ๋ ๋ฐ์ดํฐ๋ ์ฐ์ง ๋ชปํ๋๋ฐ ๋ฉ๋ชจ๋ฆฌ์์ ๋ด๋ ค๊ฐ์๋ ๊ฒฝ์ฐ๊ฐ ๋ฐ์ํ ์ ์๋ค.
class Customer {
let name: String
var card: CreditCard?
init(name: String) {
self.name = name
}
deinit { print("\(name) is being deinitialized") }
}
class CreditCard {
let number: UInt64
// customer ๋ฅผ unowned ๋ณ์๋ก ์ค์ .
// weak ๊ณผ ๋ฌ๋ฆฌ ์๋์ผ๋ก nil ์ด ํ ๋น๋์ง ์์ผ๋ฏ๋ก let ๊ฐ๋ฅ.
unowned let customer: Customer
init(number: UInt64, customer: Customer) {
self.number = number
self.customer = customer
}
deinit { print("Card #\(number) is being deinitialized") }
}
var john: Customer? // nil
john = Customer(name: "John Appleseed") // Customer ARC 1
john!.card = CreditCard(number: 1234_5678_9012_3456, customer: john!) // CreditCard ARC 1
๋ง์ฝ john ์ ๋๋๋ค๋ฉด
CreditCard ARC 1
Customer ARC 0
์ด ๋์ด์, Customer ๊ฐ ๋ด๋ ค๊ฐ๊ณ , CreditCard ๋ ๋ด๋ ค๊ฐ๋ค. CreditCard ๋ ๊ฐ์ด ๋ด๋ ค๊ฐ๋ ๊ฒ. ๋จ์์ ์ฐ์ด์ง ์๊ธฐ ๋๋ฌธ์ unowned ๊ฐ ๊ฐ๋ฅํ๋ค.
john = nil
// Prints "John Appleseed is being deinitialized"
// Prints "Card #1234567890123456 is being deinitialized"
๋์ unowned ๋ฅผ ์ฌ์ฉํ ๋๋ ์ ๋ง๋ก ์ฐธ์กฐํ๊ณ ์๋ ๊ฒ์ด ๊ฐ์ด ํน์ ๋์ค์ ๋ด๋ ค๊ฐ๋ ๊ฒ์ด ๋ง๋์ง์ ๋ํด ์ ํํ๊ฒ ๊ฒ์ฆํด์ผ ํ๋ค.
unowned
๋ก ํ๊ธฐํ ์ ์๋ค.class Department {
var name: String
// ๊ฐํ ์ฐธ์กฐ.
var courses: [Course]
init(name: String) {
self.name = name
self.courses = []
}
}
class Course {
var name: String
// ๋ฏธ์์ ์ฐธ์กฐ.
unowned var department: Department
unowned var nextCourse: Course? // ๋ฉ๋ชจ๋ฆฌ์์ ํด๋น ๋ณ์๋ค์ด ๋จผ์ ๋ด๋ ค๊ฐ ๋ฒ๋ฆฌ๋ฉด nil
init(name: String, in department: Department) {
self.name = name
self.department = department
self.nextCourse = nil
}
}
์๋์ ๊ฐ์ ์ํฉ์ด๋ผ๋ฉด, department ๊ฐ ๋์ด์ง๋ ์๊ฐ, department ๋ฅผ ๊ฐํ๊ฒ ์ฐธ์กฐํ๋ ๋ณ์๊ฐ ์์ด์ department ๋ด๋ ค๊ฐ๊ณ , ๊ทธ๋ฌ๋ฉด Course ๋ฐฐ์ด ์์ ๊ฐ ์ฝ์ค๋ค๋ ๋ด๋ ค๊ฐ๊ฒ ๋๋ค.
๋ฐ๋ก ๊ฐ์ด ๋ด๋ ค๊ฐ๋๊น unowned ์ฌ์ฉ ๊ฐ๋ฅ.
let department = Department(name: "Horticulture")
let intro = Course(name: "Survey of Plants", in: department)
let intermediate = Course(name: "Growing Common Herbs", in: department)
let advanced = Course(name: "Caring for Tropical Plants", in: department)
intro.nextCourse = intermediate
intermediate.nextCourse = advanced
department.courses = [intro, intermediate, advanced]
NOTE : ์๋ value type ์ unowned ๋ก ํ์ํ ์๊ฐ ์๋ค. ๊ทธ๊ฒ์ด Swift ์ ๊ท์น์ (์ฐธ์กฐ๋ class ๋ง ํ๋๊น) ๊ทผ๋ฐ, Optinal ์ enum ์ด์ง๋ง unowned ๋ก ํ๊ธฐํ ์ ์๋ ์์ธ๊ฐ ์๋ค.
Optional("class instance") ๋ ์ฐธ์กฐ ์นด์ดํธ๋ฅผ ์ฌ์ฉํ์ง ์๊ธฐ ๋๋ฌธ์, ๊ฐํ ์ฐธ์กฐ๋ฅผ ์ ์งํ ํ์๊ฐ ์๋ค.
Type!
์ ์ฐ๋ฉด ํด๋น ๊ตฌ์กฐ์ฒด, ์ด๊ฑฐํ, ํด๋์ค๊ฐ ๊ฐ์ง ๋ชจ๋ ์ ์ฅ ํ๋กํผํฐ๊ฐ ์ด๊ธฐํ ๋๊ธฐ ์ ์ self ์ ์ ๊ทผํ ์ ์์๋ ๊ฒ๊ณผ ๋ฌ๋ฆฌ,Type!
์ ํ์
์ผ๋ก ์ฌ์ฉํ ํ๋กํผํฐ๋ง ์ ์ธํ ๋๋จธ์ง๊ฐ ์ด๊ธฐํ ๋๋ฉด self ์ ์ ๊ทผํ ์ ์๋ค.class Country {
let name: String
var capitalCity: City! // ๊ธฐ๋ณธ nil ์ด๊ธฐ ๋๋ฌธ์, init์์ name ๋ง ์ด๊ธฐํํ๋ฉด Country ์ธ์คํด์ค๊ฐ ์๋ฒฝํ๊ฒ ์ด๊ธฐํ ๋ ๊ฒ์ผ๋ก ๊ฐ์ฃผํ๋ค.
init(name: String, capitalName: String) {
self.name = name
// ์ฌ์ค country ๊ฐ ์๋ฒฝ ์ด๊ธฐํ ๋๊ธฐ ์ ์๋, self ์ ์ ๊ทผํ ์๊ฐ ์์.
// City! ๋ผ๋ ์์์ ์ธ๋ํ์ ์ฌ์ฉํ๋ฉด name ์ด ์ค์ ๋์๋ง์ self ์ ์ ๊ทผํ ์ ์๋ค.
self.capitalCity = City(name: capitalName, country: self)
}
}
class City {
let name: String
unowned let country: Country
init(name: String, country: Country) {
self.name = name
self.country = country
}
}
// ๋๋ํ ์์ฐ๊ณ capitalCity ์ ๊ทผ๋ ๊ฐ๋ฅํ๋ค.
var country = Country(name: "Canada", capitalName: "Ottawa")
print("\(country.name)'s capital city is called \(country.capitalCity.name)")
// Prints "Canada's capital city is called Ottawa"
์์์ ํด๋์ค ์ธ์คํด์ค ํ๋กํผํฐ๊ฐ ์๋ก ๊ฐํ ์ฐธ์กฐ๋ฅผ ์ ์งํด์ ๊ฐํ ์ฐธ์กฐ ์ฌ์ดํด์ด ์๊ธฐ๋ ๊ฒฝ์ฐ๋ฅผ ๋ดค๋๋ฐ,
ํด๋ก์ ์ญ์ ์ฐธ์กฐํ์ ์ด๊ธฐ ๋๋ฌธ์
ํด๋์ค ์ธ์คํด์ค์ ํ๋กํผํฐ์ ํด๋ก์ ๋ฅผ ํ ๋นํ๊ณ ,
ํด๋น ํด๋ก์ ์ ๋ฐ๋์์ ์ธ์คํด์ค self
๋ฅผ ์บก์ณํ๋ ๊ฒฝ์ฐ์๋ ๋ฐ์ํ ์ ์๋ค.
class HTMLElement {
let name: String
let text: String?
// ํด๋ก์ ๋ณ์. self ์บก์ณ. lazy ๋ผ์ self ์ ์ ๊ทผ ๊ฐ๋ฅ.
// text ๊ฐ ์์ผ๋ฉด <tag>text</tag>
// ์์ผ๋ฉด <tag /> ๋ก ๋ฐํ.
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")
}
}
์ด๋ฐ ์์ผ๋ก ์ฌ์ฉ ๊ฐ๋ฅ.
var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world") // Optinal(HTMLElement)
print(paragraph!.asHTML())
// Prints "<p>hello, world</p>"
ํด๋ก์ ์ paragraph ๊ฐ ์ฐธ์กฐํ๊ณ ์๋ ์ธ์คํด์ค๊ฐ ์๋ก๋ฅผ ๊ฐํ ์ฐธ์กฐ ์ฌ์ดํด์ ๋ชฐ์๋ฃ๊ฒ ๋๋ค.
์๋ ์ฝ๋๋ก๋ ๋น์ฐํ ์ฌ์ดํด์ด ๋๊ธฐ์ง ์์.
paragraph = nil
NOTE : ์ ์ด์ ํด๋ก์ ์์์๋ self.method()
, self.property
์ฒ๋ผ self ๋ฅผ ๋ช
์ํด์ผ ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ฐ, ์ํ ์ฐธ์กฐ ๊ฐ๋ฅ์ฑ์ ์๊ฐํด๋ณด๋ผ๋ ๋ป์ด๋ค.
ํด๋ก์ ๋
self
๊ฐ์ ํด๋์ค ์ธ์คํด์ค๋ฅผ ์บก์ฒํ ์ ์๊ณ , self, ํ๋กํผํฐ ๊ฐ๊ฐ์ weak / unowned ์ค์ ์ ํด์ค ์ ์๋ค.
lazy var someClosure = {
[unowned self, weak delegate = self.delegate]
(index: Int, stringToProcess: String) -> String in
// closure body goes here
}
// ์ปจํ
์คํธ ์ ์ถ ์ฌ์ฉ.
lazy var someClosure = {
[unowned self, weak delegate = self.delegate] in
// closure body goes here
}
class HTMLElement {
let name: String
let text: String?
// HTMLElement ์ธ์คํด์ค๊ฐ ๋ด๋ ค๊ฐ ๋ ์๋ ๋ด๋ ค๊ฐ์ผํ๋๊น unowned
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 being deinitialized")
}
}
var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world")
print(paragraph!.asHTML())
// Prints "<p>hello, world</p>"
์ฐธ๊ณ
https://bbiguduk.gitbook.io/swift/language-guide-1/automatic-reference-counting