iOS

iOS ) weak self / unowned self 비교

유사앱등이 2023. 10. 4. 10:15

 

 

순환참조 문제를 방지하기 위해 약한 참조를 사용해야 할 때가 있는데,

약한 참조에도 두 종류가 있다.

weak self, unowned self인데 두 가지에 대해 정리를 해보려고 한다.


 

weak self

 

optional 타입으로 사용되며, self가 nil이 될 수 있음을 의미한다. 

옵셔널 바인딩 / 체이닝 등을 사용해야 한다.

weak self로 참조한 경우 해당 객체가 메모리에서 해제될 때 자동으로 nil로 설정된다.


 

unowned self

 

non-optional 타입이며, self가 항상 값이 있음을 의미한다. 

클로저 구문이 끝날 때도 항상 selfㄱ

 

 

 


 

클로저 내부, 특히 escaping 구문과 같이 비동기 처리를 하는 부분에서 self를 그대로 사용해버리면 문제가 발생하게 될 때가 있다.

가령, api로부터 데이터를 받아올 때 작업이 완료되기 전에 self가 메모리에서 해제되어 버릴 때 문제가 발생할 수 있게 된다.

이런 경우에는 unowned self가 아닌 weak self를  사용해야 한다.

 

 

// unowned self

class MyViewController: UIViewController {
    func fetchData() {
        networkManager.fetchData { [unowned self] data in
            // 이 시점에서 self(MyViewController)는 메모리에서 이미 해제되었을 수 있습니다.
            // 따라서 아래 코드는 런타임 오류를 발생시킬 가능성이 있습니다.
            self.updateUI(with: data)
        }
    }
}

// weak self

class MyViewController: UIViewController {
    func fetchData() {
        networkManager.fetchData { [weak self] data in
            // self가 nil인 경우 아래 코드는 그냥 무시됩니다.
            // 따라서 앱은 안전하게 실행됩니다.
            self?.updateUI(with: data)
        }
    }
}

 

 

 

정리하자면, 

순환 참조가 발생할 가능성이 있어서 약한 참조를 사용해야 할 경우 

unowned self를 사용하면

optional에 대한 처리를 추가로 하지 않아도 되기 때문에 번거롭지 않지만,

self가 nil이 되지 않는다는 걸 보장할 수 있는 경우에만 사용할 수 있고,

 

weak self를 사용하면

비교적 안전하게 사용할 수 있지만

optional에 대한 처리를 따로 해줘야 한다는 번거로움이 있다.

 

따라서 유동적으로 상황에 따라 적절한 방법을 사용하면 될 것이다.

사실 optional 처리를 하는 부분은 크게 번거로울 것이 없기 때문에 이왕이면 weak self를 사용하면 되지 않을까 싶긴 한데..

잘못된 생각일 수도 있고... 우선은 알아두는 것이 좋을 듯

순환 참조를 막고자 하는 상황이 발생했을 때 생각해볼 수 있는 게 더 늘어난 것으로 만족..!