문제해결
final class CustomAlbumViewController: UIViewController {
private func checkCameraAuthorization() {
let authorization = AVCaptureDevice.authorizationStatus(for: .video)
switch authorization {
case .notDetermined:
AVCaptureDevice.requestAccess(for: .video) { @Sendable granted in
if granted {
Task { [weak self] in
await self?.openCamera()
}
}
}
...
}
}
private func openCamera() {
// 대충 카메라 화면 띄우기..
}
}
위 코드에서 @Sendable을 붙이지 않으면 Thread 16: EXC_BREAKPOINT (code=1, subcode=0x105a80214)
잘못된 접근에 대한 에러가 발생한다.
추가로 openCamera()는 동기 메소드인데, @Sendable이 있으면 await를 붙여야 한다.
@.Sendable이 없으면 왜 위처럼 에러가 발생할까 ?
그리고 또 하나, 동기 메소드를 실행하더라도 @.Sendable 클로저 내라면 왜 await를 붙여야할까 ?
해결과정
AVCaptureDevice.requestAccess(for: .video) 정의 살펴보기
해당 AVCaptureDevice.requestAccess(for: .video)
에 정의를 보면 다음과 같이 돼 있다.

그리고 살짝 위로 올리면

The completion handler is called on an arbitrary dispatch queue. It is the client's responsibility to ensure that any UIKit-related updates are called on the main queue or main thread as a result.
번역하면 다음과 같음
완료 핸들러는 임의의 디스패치 큐에서 호출됩니다. UIKit 관련 업데이트가 결과적으로 메인 큐 또는 메인 스레드에서 호출되도록 하는 것은 클라이언트의 책임입니다.
즉, 컴플리션 핸들러가 다른 백그라운드 메소드에서 돌 테고, UI 관련 작업할 거면 니가 알아서 메인 스레드에서 돌려라.
따라서 @Sendable이 없으면 에러가 발생했던 이유가 해당 클로저가 다른 스레드에서 돌 수 있게끔 안정성을 보장하기 위해 @Sendable을 붙여줘야 했다.
동기 메소드에 await를 해줘야 하는 이유
또한, openCamera() 메소드는 동기 메소드이다.
그리고 뷰컨트롤러에 존재하는 메소드이다.
뷰컨트롤러는 @MainActor가 선언되어 있어서 openCamera() 메소드는 메인액터에 격리되어 있다.
@Sendable에 의해 백그라운드 스레드에서 openCamera를 실행시킬 수도 있다는 말인 즉슨, 메인액터에 격리된 메소드를 실행하기 위해서는 await를 붙여서 호출해야 한다는 것이다.
왜냐하면 액터에 격리된 것의 경우 하나의 액터만 접근할 수 있기 때문이다.
Swift 동시성 시스템에서 액터 간 전환은 항상 await
를 요구하니까
배운 점
- 컴플리션 핸들러가 백그라운드 스레드에서 도는 거기 때문에 @Sendable이 필요한 거다.
즉, @Sendable을 붙이지 않으면 백그라운드 스레드에서 동작 시 잘못된 접근 에러가 발생할 수 있다. - @Sendable을 준수하는 클로저까지 왔다면, openCamera() 메소드는 await로 실행되어야 한다.
왜냐하면 MainActor(뷰컨메소드)에 isolated 격리되어 있기 때문에 하나의 개체만 실행할 수 있으므로 await를 붙여서 하나의 액터만 해당 메소드를 사용할 수 있게 한다.
동기 메소드라 await가 필요없지만, 메인액터에 격리되어 있기 때문에 await를 붙여야 하는 것.
레퍼런스
https://developer.apple.com/forums/thread/764777?answerId=807248022#807248022
Request authorization for the noti… | Apple Developer Forums
I presume that getNotificationSettings() is a method on an main-actor-isolated type, like your app delegate. If it isn’t, you don’t get this error. If so, the easiest fix is to mark getNotificationSettings() as nonisolated. Share and Enjoy — Quinn
developer.apple.com
'📱 iOS > Swift Concurrency' 카테고리의 다른 글
[Swift Concurrency 11편] Main Actor (0) | 2025.02.26 |
---|---|
[Swift Concurrency 10편] Actor는 한글 키보드로 'ㅁㅊ색' 이란 걸 아시나요? (0) | 2025.02.26 |
[Swift Concurrency 9편] Sendable 프로토콜 (0) | 2025.02.26 |
[Swift Concurrency 8편] Task와 구조화된 동시성(= Structed Concurrency) (0) | 2025.02.26 |
[Swift Concurrency 7편] 비동기 호출에서의 스레드 제어권 (0) | 2025.02.26 |