iOS Swift - Memory

longlivedrgn·2022년 9월 9일
0

swift문법

목록 보기
18/36
post-thumbnail

ARC

  • Automatic Reference Counting
  • 더 이상 필요가 없는 클래스의 instance를 메모리에서 자동으로 삭제하는 것
  • Instance를 참조하는 count를 센다. 그래서 count = 0, 즉 아무것도 instance를 참조하지 않는다면 그때 instance를 메모리에서 자동으로 삭제를 한다.
  • 즉, 상수나 변수에 클래스 인스턴스를 할당하면 해당 instance에 대한 강한 참조가 생성이된다.

아래와 같이 class 두개를 생성한다고 해보자

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?
  • 그러면 아래와 같이 두 변수는 클래스 인스턴스와 강한 참조를 하게 된다.

  • 그리고 아래와 같이 john.apartment와 unit4A.tennant에 서로를 넣어준다.

john!.apartment = unit4A
unit4A!.tenant = john
  • 그러면 아래와 같이 서로 강한 참조를 하게 된다.

  • 그리고 난 다음 john과 unit4A에 nil을 할당하게 해보자
john = nil
unit4A = nil
  • 그러면 아래와 같은 참조 관계를 가지게 된다. 즉 상수나 변수는 사라졌지만, 클래스 인스턴스를 서로를 참조하고 있기에 count = 1이다. 따라서 이 두개의 클래스 인스턴스는 사용이 되지 않아도 계속해서 메모리에 존재하고 있는 것이다. -> 이러한 상황을 강한참조라고 한다.

참고 참조/ https://zeddios.tistory.com/1213

  • 이러한 경우를 해결하는 방법은 weak와 unowned을 사용하는 것이다.

Weak

-> 말 그대로 약한 참조입니다.(Count를 증가시키지 않는다)

아래와 같이 class 생성하자. 그런데 tenant를 weak로 설정하자.

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 }
    // tenant를 weak로 설정하자.
    weak var tenant: Person?
    deinit { print("Apartment \(unit) is being deinitialized") }
}
  • 그리고 instance를 생성해주자
var john: Person?
var unit4A: Apartment?

john = Person(name: "John Appleseed")
unit4A = Apartment(unit: "4A")

john!.apartment = unit4A
unit4A!.tenant = john
  • 그러면 아래와 같은 관계가 설정이 된다.

  • 이러한 상황에서 만약 john에 nil을 선언한다면? count는 0이 되면서 deinit이 된다!

john = nil
// Prints "John Appleseed is being deinitialized"
  • 그리고 원래 있던 tenant는 nil로 설정이된다.

따라서 weak의 경우 아래의 두 조건을 고려해줘야된다.
-> 값이 nil로 변경될 수 있으므로 항상 Optional로 선언되어야한다.
-> nil로 변경이 될 수 있으므로 var로 선언을 해주어야된다.

Unowned

새로운 class를 아래와 같이 생성해준다.(unowned를 사용)

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
    // unowned 상수를 설정
    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?
  • 그리고 할당을 시킨다.
john = Customer(name: "John Appleseed")
john!.card = CreditCard(number: 1234_5678_9012_3456, customer: john!)
  • 그러면 아래와 같은 관계가 형성이된다.

그런데, 만약 john에 nil을 할당하면? -> 둘다 deinit이 된다.

근데, unowned의 경우 nil이 되지 않으므로 let으로도 선언가능

참고 참조-
https://zeddios.tistory.com/1213

0개의 댓글