ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [RxSwift] weak, unowned self에 대한 의문
    iOS/RxSwift 2022. 1. 27. 23:57

    일단 기본적으로 두 용어의 개념은 생략하고 쓰임새를 써보자면 다음과 같다.

    weak는 객체를 Optional로 참조하기 때문에, 참조하는 객체가 도중에 사라질 가능성이 있을 때 사용한다.

    unowned는 객체를 Non Optional로 참조하기 때문에, 참조하는 객체가 항상 존재함(필요할 때)을 가정한다.

    weak는 필요할 때마다 Unwrapping에 대한 코드를 작성해야 하기 때문에 불편하다..

    기존에 갖고있던 생각

    이제 RxSwift에서 두 키워드의 쓰임에 대해서 생각해보자.

    RxSwift에는 Observable의 생명주기를 관리(?)해주는 dispose 메서드, 그것을 더 편하게 도와주는 DisposeBag이 있다.

    DisposeBag은 최대 생명주기가 부모객체의 생명주기와 같다.

    부모 객체가 deinit되면 DisposeBag도 deinit되면서 갖고있던 모든 Observable을 dispose해준다.

    즉, disposeBag에 등록 해 놓으면, 해당 부모 객체보다 더 오래 살아남을 가능성은 0(지-로) 이다.

    그 말은 즉, disposeBag에 등록해놓으면, unowned self를 써도 된다! 였다.

    왜냐면 Observable은 최소, 그 부모객체랑 같이 deinit되기 때문에 캡쳐 하고있는 객체가 항상 존재함이 보장되기 때문이다.

    ARC의 동작방식을 간과했다.

    ARC의 동작방식의 이해

    이것도 간단하게 적어보자면, 객체의 참조카운트가 0이 되었을 때 해당 객체를 메모리에서 해제해준다.

    OBJ-C에서의 MRC의 경우 참조카운트를 관리해주는 구문을 직접 작성해주어야 했는데, ARC의 경우에는 컴파일 시점에 자동으로 작성해준다.

    즉, 참조카운트가 0이 되어야만 메모리가 해제된다.

    이제 생각해보자. 아래 상황에서 캡쳐를 weak, unowned로 했다고 가정하자.

    http://adamborek.com/memory-managment-rxswift/

    MyViewController Deinit -> DisposeBag Deinit -> Disposable Dispose -> Observable Deinit

    이런 순서로 진행될 것이다. 이제 무언가 보인다. MyViewController의 Deinit과 Observable의 Deinit사이에는 약간의 시간차이가 존재한다.

    아마도 이 사이에 Observable에서 MyViewController를 참조하는 행위가 발생하게 되면, 그 때 Crush가 날 가능성이 있기 때문에 unowned self를 사용하지 말라고 하는 것 같다.

    Do not use unowned self

    https://github.com/RxSwiftCommunity/RxDataSources/issues/169#issuecomment-331642501

    아무리 생각해도 unowned, weak를 써야하는 시점을 구분해서 사용해 주는것이 명확한 코드라고 생각하지만

    일단은.. 확실하게 알아내기 전 까지는 weak를 사용하는 쪽으로 마음을 굳혔다.

    'iOS > RxSwift' 카테고리의 다른 글

    [RxSwift6] "withUnretained" operator로 리펙토링하기  (0) 2022.02.02
    [RxSwift] Error Handling [2]  (0) 2022.01.27
    [RxSwift] Error Handling [1]  (0) 2022.01.25
    RxSwift로 리펙토링 맛보기  (0) 2022.01.03
    [Rxswift] 03.Subjects  (0) 2021.12.19

    댓글

Designed by Tistory.