inblog logo
|
iOS.dev
    Swift

    [Swift] @escaping 클로저와 순환참조

    Swift의 escaping 클로저와 순환참조의 정리
    Aug 20, 2023
    [Swift] @escaping 클로저와 순환참조
    Contents
    @escaping 클로저와 순환참조
    Swift에서는 함수가 1급객체이기 때문에 함수를 매개변수로 넣을수가 있습니다.
     
    이 때 함수가 끝나고 실행되거나 함수 밖에 저장되는 클로저일 때,
    (onNext, onComplete, onError이벤트 클로저 같은)
    보통 비동기 작업 후 실행되는 (completeHander로 많이 쓰이는)클로저는 매개변수 타입 앞에 @escaping 키워드를 명시해주어야 합니다.
    명시해주지 않았을 때에는 error가 발생합니다.
    (converting non-escaping parameter '(매개변수 명)' to generic parameter 'Element' may allow it to escape)
    // 함수를 저장해놓기 위한 배열 var completeHandlers = [() ->Void]() // completeHandlers에 함수를 저장하는 함수 func addCompleteHandler(completeHander:@escaping () ->Void) { completeHandlers.append(completeHander) }
     

    @escaping 클로저와 순환참조

    escaping클로저 내에서 self를 참조해야할 때가 있습니다.
    클로저 내부에서 인스턴스를 참조를 하게 되었을 때 강한 순환참조가 발생할 수가 있습니다.
    (non-escaping클로저라면 self를 참조해도 클로저 내에서 작업을 마치고 메모리 해지가 되기 때문에 상관이 없습니다)
    // 함수를 저장해놓기 위한 배열 var completeHandlers = [() ->Void]() class SomeClass { var someValue = 10 // completeHandlers에 함수를 저장하는 함수 func addCompleteHandler(completeHander:@escaping () ->Void) { completeHandlers.append(completeHander) } func someFunc() { addCompleteHandler(completeHander: { self.someValue += 10 // self(SomeClass의 인스턴스)가 캡쳐 print("addedHandler: \(self.someValue)") }) } }
    이런 경우 SomeClass 인스턴스의 someFunc()에서 addCompleteHandler로 클로저를 전달하여 completeHandlers에 저장되고,
    전달한 클로저에서 self(SomeClass의 인스턴스)의 참조 카운트가 올라가게 되는데,
    someClass인스턴스를 다 사용하고 난 뒤에도 카운트가 남게되어 메모리 누수가 될 수 있습니다.
    그래서 클로저의 인스턴스 참조로 안한 강한 순환참조를 없애기 위해 [weak self]를 사용합니다.
     
    1) 아래처럼 [weak self]로 선언 후 옵셔널 체이닝으로 사용을 하거나,
    addCompleteHandler(completeHander: { [weakself] in self?.someValue += 10 print("addedHandler: \(self?.someValue)") })
     
    2) guard let self = self 로 빠른 탈출 구문으로 사용하는 방법이 있습니다.
    addCompleteHandler(completeHander: { [weakself] in guard let self = self else { return } self.someValue += 10 print("addedHandler: \(self.someValue)") })
     
    Share article

    iOS.dev

    RSS·Powered by Inblog