ARC를 이해하고나서 weak와 unowned를 아무리 생각해도 이해할 수 없었는데, 드디어 오늘 이해하여 게시물로 생각을 다시 한번 정리해 보았음.
weak와 unowned가 RC를 올려주지 않는다는건 알고 있었음. 근데, 변수로 담으면 사용할 수 있으니까 RC를 올려주는거 아닌가? 같은 의문으로 햇갈리기 시작했음.
그러니까.. 처음에 이해했을땐 weak와 unowned는 RC를 한 0.5 정도 올려주는건가? 라는 생각으로 지금까지 살아왔는데, 오늘 실험으로 그 신념이 깨졌음.
class Guild {
var name: String
init(name: String) {
self.name = name
}
deinit { print("Guild Deinit \(name)") }
}
weak var guild: Guild? = Guild(name: "Mcflurry")
Guild를 만들고 weak로 만들면, guild를 통해서 name에 접근할 수 있을 줄 알았는데, 선언하자마자 deinit이 실행이 되어 사용하지 못하게 됨.
그러니까, init되자마자 deinit이 되어버린것.
그리고 한가지 더 햇갈렸던것. deinit시 내부 프로퍼티를 가지고 나갈수 있나 해서 해봤는데, 아주 잘 실행되는걸 볼 수 있었다.
Guild Deinit Mcflurry
그럼 이제 시작
은 솔직히 다른 곳에서도 좋은 설명 많으니까, 이번에 이해한 차이점을 위주로 적어보겠음. 그래도 단순 나열 하자면,
머리속으로 차이점은 이해하고 있었는데, 아직 가슴으로는 이해하지 못하고 있었다. 실험 전 weak에 대해 알고있는 지식으로는,
마지막줄이 조금 가슴으로 이해가 덜됬는데 코드를 보자면,
class Guild {
var name: String
weak var king: User?
init(name: String) {
self.name = name
}
deinit { print("Guild Deinit \(name)") }
}
class User {
var nick: String
init(nick: String) {
self.nick = nick
}
deinit { print("User Deinit") }
}
var guild: Guild? = Guild(name: "Mcflurry")
var user: User? = User(nick: "프로미스나인")
guild?.king = user
user = nil // print -> User Deinit
print(guild?.king)
guild에서도 user를 바라보고 있으니 RC가 2가 되어서, user를 nil로 할당해도 꺼지지 않아야 하는데, weak로 선언했으므로 user의 RC는 nil로 할당한 시점에서 0이 되어 deinit이 실행되었고, deinit이 되었기 때문에 guild?.king에 접근했을때 nil이 나온다.
그렇다면 unowned는?
보기 전에 전제를 한번 깔아보도록 하자.
Guild의 king은 무조건 존재한다.
이 전제를 깔고 다시 코드를 보겠다.
class Guild {
var name: String
unowned var king: User?
init(name: String) {
self.name = name
}
deinit { print("Guild Deinit \(name)") }
}
class User {
var nick: String
init(nick: String) {
self.nick = nick
}
deinit { print("User Deinit") }
}
var guild: Guild? = Guild(name: "Mcflurry")
var user: User? = User(nick: "프로미스나인")
guild?.king = user
user = nil
print(guild?.king)
이대로 실행하게 되면 마지막 print에선 다음과 같은 오류 메시지가 출력된다.
Fatal error: Attempted to read an unowned reference but object 0x60000021af20 was already deallocated
코드를 설명하자면, 앞서 전제가 Guild에는 King이 무적권 있어야 하는데, user가 nil이 되어버려서 king이 사라져버린것.
여기서 weak와 unowned의 차이를 알 수 있는데, weak는 대상이 nil이 되어버리면 자동으로 nil을 할당하면서 프로퍼티에서 갖고 있는 메모리 주소도 자동으로 삭제해 버리지만, unowned는 그렇지 않다. RC가 줄어들어 deinit이 됨은 분명하나, nil이 되었음에도 불구하고 프로퍼티에서 메모리 주소를 아직 갖고 있는 상태가 된다.
따라서 unowned는, 나 자신(Guild)보다 상대(user)가 더 메모리상에서 수명이 길어야 할때 사용해야한다.