관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] Escaping closure captures mutating 'self' parameter 에러 원인 및 해결 방법 ([self]를 쓰는 이유, memory safety, memory access conflict) 본문

iOS 응용 (swift)

[iOS - swift] Escaping closure captures mutating 'self' parameter 에러 원인 및 해결 방법 ([self]를 쓰는 이유, memory safety, memory access conflict)

jake-kim 2023. 7. 30. 01:37

Escaping closure에서의 self 캡쳐

  • value type인 struct의 mutating 키워드가 붙은 메서드에서, 클로저(escaping closure)내부에 self를 참조하는 경우에 발생

  • 오류가 발생하는 이유
    • swift에서는 memory safety을 지키기 위해서 컴파일러 타임에 이런 케이스를 사전에 방어해주기 위해 이런 컴파일 에러를 표출
    • memory safety 개념은 이전 포스팅 글 참고

ex) memory safety하지 않은, memory access conflict 발생 코드

  •  value타입에서 set과 get이 동시에 일어나는 경우

  • 다시 돌아와서, "Escaping closure captures mutating 'self' parameter" 에러가 나는 이유?
    • value type에서는 memory safety하게 관리하지 않으면 크래시가 발생하므로, 언제 실행될지 모르는 esacping closure 안에서 self에 대한 변경사항이나 참조를 하려고 하면 memory access conflict 가 발생할 수 있으므로 컴파일러 단에서 오류를 알림

정리

  • value type 안에서 같은 메모리에 대해서 get, set이 동시에 일어나는 상황을 막아주기 위해 컴파일러가 esacping closure안에서 self 캡쳐하는 것을 막음
  • getter에 대해서도 컴파일 에러
    • print(self.value)만 해도 에러가 발생

  • 해결 방법?
    • escaping closure 안에서는 메모리가 다른 self를 캡쳐하게 해주면 해결
    • escaping 시점에 self를 복사해주어 새로운 메모리 할당
    • (getter는 이 방법으로 가능하지만, setter는 불가)
struct MyStruct {
    var value = 0

    mutating func updateValue(completion: @escaping () -> Void) {
        DispatchQueue.main.async { [self] in // <- escaping 시점에 self를 복사해주어 새로운 메모리 할당
            print(self.value)
            completion()
        }
    }
}

* 전체 코드: https://github.com/JK0369/ExMemorySafety_value_type

Comments