FamilyActivityPicker: Crash Handling in UIKit context #2 에서 살펴본대로, .familyActivityPicker 메서드를 활용하면 우회방법을 통한 Crash Handling을 구현하기가 어려울 것 같아서, 새로 SwiftUI 뷰를 구성해주기로 했다. 해보니까 생각보다 어렵지 않았다.
import SwiftUI
import FamilyControls
struct FamilyActivityPickerView: View {
@Environment(\.dismiss) private var dismiss
@Binding var selection: FamilyActivitySelection
@State private var tempSelection: FamilyActivitySelection
init(selection: Binding<FamilyActivitySelection>) {
self._selection = selection
self._tempSelection = State(initialValue: selection.wrappedValue)
}
var body: some View {
VStack(spacing: 0) {
HStack {
Button("취소") {
dismiss()
}
Spacer()
Button("저장") {
selection = tempSelection
}
}
.padding()
.background(Color(UIColor.systemBackground))
.foregroundStyle(.white)
FamilyActivityPicker(selection: $tempSelection)
}
.ignoresSafeArea(edges: .bottom)
}
}
tempSelection을 물게 했더니, 항목을 선택했을 때 바로 닫혀버리는 문제가 사라졌다.
FamilyActivityPicker가 UIKit Context에서도 잘 작동하도록 이와 같이 구성해주었다.
이를 불러오는 부분은 아래와 같이 구현되어있다:
private func appPicker() {
// UIKit 기반인 ViewController에서 SwiftUI 기반의 View를 불러오기 위한 임시 변수
let tempSelectionBinding = Binding<FamilyActivitySelection>(
get: { [weak self] in self?.familyActivitySelection ?? .init() },
set: { [weak self] in self?.familyActivitySelection = $0 }
)
let hostingVC = UIHostingController(
rootView: FamilyActivityPickerView(selection: tempSelectionBinding)
)
// hostingVC 설정 갱신을 통해 실제 구현
let selectionBinding = Binding<FamilyActivitySelection>(
get: { [weak self] in self?.familyActivitySelection ?? .init() },
set: { [weak self] newSelection in
self?.familyActivitySelection = newSelection
self?.viewModel.blockListRelay.accept(newSelection)
hostingVC.dismiss(animated: true)
}
)
let pickerView = FamilyActivityPickerView(selection: selectionBinding)
hostingVC.rootView = pickerView
hostingVC.modalPresentationStyle = .overFullScreen
hostingVC.view.backgroundColor = .clear
self.isFamilyActivityPickerPresented = true
self.present(hostingVC, animated: true, completion: nil)
}

새로 발생한 문제점들:
1. 취소와 저장 버튼에 뒤따라오는 FamilyActivityPicker가 늦어서 끊어져보이는 문제 (Opal은 로딩스크린을 집어넣어서 해결함)
2. 불러왔을 때 애초에 크래쉬가 발생한 경우: 기존 사용하려던 우회방법을 사용하면 해결되기는 하는데.. UX 측면에서 상당히 나쁠 것 같다.
새로 발생한 문제는 별개로 해결한다 치고, 이제 Crash Handling을 적용해주면 된다. 기존에 참고한 자료에 따르면 ZStack으로 화면 뒤편에 미리 알럿창을 띄워두고 1초마다 업데이트 해주는 우회방법을 사용하면 되는데..
그 전에 디버깅을 하다가 발견한 오류에 조금 주목해보기로 했다.

어쩌면 FamilyControls.ActivityPickerRemoteViewError 라는 녀석을 감지만 할 수 있다면 트리거로 사용할 수 있지 않을까? Opal 개발자는 저걸 발견해서 사용하고 있을지도 모른다.