먹고 기도하고 코딩하라

[Xcode] 14.3와 [weak self] 캡처 본문

[Xcode] 14.3와 [weak self] 캡처

사과먹는사람 2023. 6. 15. 22:40
728x90
728x90

 

결론

xcode 14.3부터는 이스케이핑 클로저에서 [weak self] 캡처 후 self 언랩핑을 하면, 명시적인 self를 써주지 않아도 된다 

 

 

Xcode 14.3이 릴리즈된 지 2달 반이 지났는데 급 릴리즈 노트 포스팅을 하는 건.. 오늘 빌드가 여러 번 터져서 애를 먹었기 때문이다.

원래 Xcode 13 버전을 쓰다가, 카플레이 개발하려고 올해 1월쯤 Xcode 14.1로 올렸다. 그 뒤로 업데이트를 안 하고 있다가, 최신 OS 기기 연결을 위해 14.3으로 업데이트했다.

14.3으로 업데이트한 뒤 처음에는 Missing file libarclite_iphoneos.a 하면서 빌드가 잘 되지 않았는데, 그건 이 스택오버플로우 질문 글을 통해 잘 해결했다.

팟파일로 설치한 써드파티 프레임워크가 있다면, minimum deployments를 수동으로 11.0으로 올려주고 다시 빌드하면 됐다. 우리 앱은 다행히도 11.0이 minimum 버전이라서 고민 없이 올릴 수 있었고, 프레임워크들 버전 조정 후에는 빌드가 잘 됐다. 

 

Missing file libarclite_iphoneos.a (Xcode 14.3)

After installing Xcode 14.3 in order to run my app on my iOS 16.3 iPhone XS. I get the following error: File not found: /Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.

stackoverflow.com

 

근데 그로부터 한 이삼일 지난 뒤부터 갑자기 내가 작업하던 브랜치의 자동 빌드가 잘 안 되기 시작했다.

처음에는 대수롭지 않게 여겼다. 빌드머신 가끔 뻑나서 잘 되다가도 안 되는 게 너무 예삿일이라 가볍게 생각하고 넘겼다. 그러다가 오늘 QA 티켓들 처리해서 배포하려고 빌드를 하는데, 세상에 빌드가 안 됐다.

이거 왜 안 되나 쩔쩔매면서 원격으로 빌드 머신 켜서 보는데, 에러 메시지가 떠 있었다. 이스케이핑 클로저에서 weak self 하고, guard let self 한 다음에 클로저 외부의 프로퍼티나 메소드에 접근하려고 하면 self.를 붙여줘야 하는데 그걸 안 붙여주면 뜨는, 꽤 자연스럽고(?) 자주 실수하는 것 중에 하나였다. 

근데 이상한 건.. 왜 내 xcode에서는 잘 되는 걸까 하는 거였다. 다른 건 버전뿐이 없었는데...

 

그래서 간이 실험을 해봤다. [weak self]로 캡쳐하고, guard let self로 참조를 건 다음, self 없이 프로퍼티에 접근해서 빌드하는 걸로. 정확히 아래 코드 같지는 않지만, 간단하게 참고하기 위해 만들어봤다.

class MyViewController: UIViewController {
  @IBOutlet weak var myView: UIView!
  
  // code
  
  var changeBGColorClosure = {
    { [weak self] color in 
      guard let self, let color = color as? UIColor else { return }
      // self.myView.backgroundColor = color
      myView.backgroundColor = color
    }
  }
}

내 xcode에서는 빌드에 성공했다. 원래대로라면, myView는 클로저 외부, MyVC의 프로퍼티이므로 self를 붙여줘야 빌드가 되지만 self 없이도 빌드되는 기현상이 일어난 것이다. 즉, Xcode 14.1에선 안 되지만 Xcode 14.3에선 모종의 이유로 self 캡쳐를 해 두면 self 프로퍼티나 메소드에 접근할 때 self를 붙이지 않아도 된다.

 

그 모종의 이유가 뭘까 찾아보려고 Xcode 14.3 릴리즈 노트를 훑어봤다.

 

Xcode 14.3 Release Notes | Apple Developer Documentation

Update your apps to use new features, and test your apps against API changes.

developer.apple.com

Implicit `self` is now permitted for [weak self] captures, after `self` is unwrapped.

[weak self]로 캡쳐된 self에 대해, 이 self가 언랩핑된 후에는 암묵적인 self 사용이 가능해진다.

이게 무슨 뜻이냐면... 위의 예시에서, Xcode 14.3 이전에 우리는 무조건 self.myView 식으로 명시적으로 self를 앞에 붙여줘야 했다. 하지만 14.3부터는 그런 거 안 해도 된다는 얘기다. 

swift 5에서는 논이스케이핑 클로저에서도 암묵적 self를 사용할 수 있는데, 심지어 self 언랩핑 이전에서부터 사용이 가능하다. 

class ExampleClass {
  func makeArray() -> [String] {
    // `Array.map` takes a non-escaping closure:
    ["foo", "bar", "baaz"].map { [weak self] string in
      double(string) // implicitly refers to `self!.double(string)`
    }
  } 


  func double(_ string: String) -> String {
    string + string
  }
}

xcode 14.3에 요런 기능이 추가됐기 때문에, 14.1에서는 빌드 에러가 뜨던 게 14.3에서는 에러 메시지조차 안 나오고 빌드도 잘 됐던 거다.

당분간은 빌드 머신을 14.3으로 올리지 않을 것 같아서, 그냥 내가 클로저 쓸 때 좀 조심하면서 써야될 것 같다.

 

 

728x90
반응형

'' 카테고리의 다른 글

Xcode 15에서 iOS 15 미만 기기 빌드 에러 이슈  (0) 2023.11.24
Xcode 15 App Extension 버전 조정하기  (1) 2023.11.14
Comments