본문 바로가기

swift

[swift] ARC | 약한참조 (weak)

약한참조 (weak)

약한참조 (weak) 는 강한참조와 달리 자신이 참조하는 인스턴스의 참조 횟수를 증가시키지 않는다.

참조 타입의 프로퍼티나 변수의 선언 앞에 weak 키워드를 써주면 그 프로퍼티나 변수는 자신이 참조하는 인스턴스를 약한참조한다.

약한참조를 사용한다면 자신이 참조하는 인스턴스가 메모리에서 해제될 수도 있다는 것을 예상해볼 수 있어야 한다.

자신이 참조 횟수를 증가시키지 않았기 때문에 그 인스턴스를 강한참조하던 프로퍼티나 변수에서 참조 횟수를 감소시켜 0으로 만들면, 자신이 참조하던 인스턴스가 메모리에서 해제되기 때문이다. 

 

 

약한참조와 상수, 옵셔널

약한참조는 상수에서 쓰일 수 없다.

만약 자신이 참조하던 인스턴스가 메모리에서 해제된다면 nil이 할당될 수 있어야 하기 때문이다.

또한 nil이 할당될 수 있어야 하므로 약한참조는 항상 옵셔널이어야 한다.

즉, 옵셔널 변수만 약한참조를 할 수 있다.

 

 

강한참조 순환 문제를 약한참조로 해결

class Person {
    let name: String
    
    init(name: String) {
        self.name = name
    }
    
    var room: Room?
    
    deinit {
        print("\(name) is being deinitialized")
    }
}

class Room {
    let num: String
    
    init(num: String) {
        self.num = num
    }
    
    weak var host: Person? // 약한참조 !!!!
    
    deinit {
        print("Room \(num) is being deinitialized")
    }
}

var domisol: Person? = Person(name: "domisol") // Person 참조 횟수 1
var room: Room? = Room(num: "606") // Room 참조 횟수 1

room?.host = domisol // Person 참조 횟수 그대로 1 !!!!!
domisol?.room = room // Room 참조 횟수 2

domisol = nil // Person 참조 횟수 0, Room 참조 횟수 1 !!!!!!
// " domisol ~~ deinit "
print(room?.host) // "nil"

room = nil // Room 참조 횟수 0
// " room ~~ deinit "

Room 클래스의 host 프로퍼티가 약한참조를 하도록 weak 키워드를 추가해서 정의한 코드이다.

각 Person 과 Room 인스턴스는 domisol 과 room 변수에 할당할 때 참조 횟수가 1이 된다.

그러나 room 변수가 참조하는 인스턴스의 host 프로퍼티가 약한참조를 하므로, domisol 이 참조하는 인스턴스를 room 의 host 프로퍼티에 참조하도록 할 때, 참조 횟수는 증가하지 않는다. 

또한 domisol 변수가 참조했던 인스턴스의 참조 횟수가 0이 되며 인스턴스에서 해제될 때, 이 인스턴스의 room 프로퍼티가 참조하는 room 인스턴스의 참조 횟수도 1 감소한다.

즉, 인스턴스가 메모리에서 해제될 때 자신의 프로퍼티가 강한참조를 하던 인스턴스의 참조 횟수를 1 감소시킨다는 것을 알 수 있다.

마지막으로 print(room?.host) 를 찍어보면 nil 이 출력된다. 

host 프로퍼티는 약한참조를 하기 때문에 자신이 참조하는 인스턴스가 메모리에서 해제되면 자동적으로 nil 을 할당한다 !!

 

마지막으로 room 에 nil 을 할당하며 참조 횟수를 0으로 만들고, 메모리에서 해제되도록 한다.

이렇게 약한참조를 통해 강한참조 순환 문제를 해결할 수 있다. 

 

 

참고 : 한빛미디어 swift 프로그래밍 2판

 

+

 

IBOutlet 기본값이 weak 이기도 하고,

강한참조를 하게 될 경우 메모리가 부족할 수도 있기 때문에 weak 을 사용하는 게 보편적이다.

다만, 복잡한 계층 구조를 가지고 있는 뷰에서라면, 중간에 메모리에서 해제될 수도 있으므로 strong을 사용하기도 한다. 

 

 

 

Interface Builder IBOutlet연결에 Strong과 Weak 어떤것을 써야할까? - JingyuJung's Blog

IBOutlet의 Strong vs Weak Interface Builder를 사용하는 프로젝트에서 View를 코드상에서 제어하기 위해 IBOutlet으로 스토리보드 <-> 코드 를 연결하게 됩니다. Ctrl키를 누르고 View를 .m 또는 .h 파일로 가져오�

monibu1548.github.io

'swift' 카테고리의 다른 글

[swift] 클래스(class)  (0) 2020.06.22
[swift] 구조체 (struct)  (0) 2020.06.22
[swift] ARC | 강한참조 (Strong)  (0) 2020.06.11
[swift] ARC란?  (0) 2020.06.11
[swift] 데이터 타입 | Any, AnyObject  (0) 2020.06.08