-
Notifications
You must be signed in to change notification settings - Fork 0
Description
| 구분 | weak 참조 | unowned 참조 |
|---|---|---|
| 형태 | Optional | Non-Optional |
| 사용 대상 | 클래스 인스턴스 프로퍼티 | 클로저 캡처 리스트 |
| 참조 대상 해제 시 | 자동으로 nil 설정 | 크래시 발생 가능 |
| 강력 순환 참조 방지 | 💡 | 💡 |
| nil 처리 필요 | 💡 | ❌ |
- weak 참조는 옵셔널 형태로 사용
- 주로 클래스 인스턴스의 프로퍼티에 사용된다.
- 참조 대상이 해제되면 자동으로 nil로 설정되므로 nil 처리가 필요!
- unowned 참조는 Non-Optional 형태로 사용됨
- 주로 클로저 캡처 리스트에서 사용됩니다. 참조 대상이 해제되면 크래시가 발생할 수 있습니다.
- weak 참조 사용 예제:
class Bodybuilder { let name: String init(name: String) { self.name = name } var gym: Gym? deinit { print("\\(name)의 보디빌더 인스턴스가 해제되었습니다.") } }class Gym {
let name: String
init(name: String) { self.name = name }
weak var trainer: Bodybuilder?
deinit { print("\(name) 헬스장 인스턴스가 해제되었습니다.") }
}
- unowned 참조 사용 예제:
class BodybuilderCoach { let name: String var bodybuildr: Bodybuilder? init(name: String) { self.name = name } deinit { print("\\(name) 트레이너 인스턴스가 해제되었습니다.") } }class Bodybuilder {
let name: String
unowned let coach: BodybuilderCoach
init(name: String, coach: BodybuilderCoach) {
self.name = name
self.coach = coach
}
deinit { print("\(name) 보디빌더 인스턴스가 해제되었습니다.") }
}
unowned 참조는 주로 클로저 캡처 리스트에서 사용됩니다. 클로저는 클로저 캡처 리스트를 통해 외부 변수나 상수를 참조할 수 있습니다. 이때 강력 순환 참조를 방지하기 위해 unowned 참조를 사용합니다.
예시:
class SomeClass { var value: Int = 0lazy var closure: () -> Void = { print(self.value) } deinit { print("SomeClass 인스턴스가 해제되었습니다.") }}
위 코드에서 closure 프로퍼티는 SomeClass 인스턴스 자신을 강력 참조하고 있어 강력 순환 참조 문제가 발생,
해결하기 위해 클로저 내부에서 self를 참조할 때 unowned를 사용.
class SomeClass { var value: Int = 0lazy var closure: () -> Void = { [unowned self] in print(self.value) } deinit { print("SomeClass 인스턴스가 해제되었습니다.") }}
이렇게 unowned 참조를 사용하면 강력 순환 참조를 방지할 수 있음.
주의점은?
unowned 참조는 참조 대상이 해제되면 크래시가 발생할 수 있다...
위 예제에서 SomeClass 인스턴스가 해제되기 전에 클로저가 실행되면 문제가 없지만
그 반대의 경우라면 크래시가 발생할 수 있다.
따라서 unowned 참조를 사용할 때는 참조 대상이 해제되기 전에 자신이 해제되리라는 가정 하에 사용해야 한다. 그외엔 weak 참조를 사용하는 것이 안전.