Composable Architectureにおけるカメラ制御の扱いのお悩み相談
こんばんは。やっと技術っぽいこと書き始めたアマゾネスです。
...といっても有益な知識共有とかではなく、お悩み相談です。ごめんなさい。
現在The Composable Architecture(以下、TCA)の構成でアプリを実装しているのですが、カメラを使用するにあたり、とても考えていることがあるで、それを共有&お力をかりたい感じです🙇♀️
悩んでいること
はじめに悩んでいるポイントをいいます。
前提:TCAで実装している
- カメラのセッション開始や終了はReducerで扱うべきか
- ViewをStateとして扱うことに違和感を感じないか
が、今回のお悩みポイントです。
それを踏まえ、中身の簡単な実装を書いていきます。
実装物は、起動時にカメラが表示されるだけのアプリです。
実装
SwiftUI
でカメラを扱う場合、UIViewControllerRepresentable
に準拠したCALayerView
を用意する必要があります。
※アーキテクチャは違いますが、全体の実装としてはこちらを参考にさせていただいています。
CALayerView
はキャプチャされたビデオを表示する必要があります。
キャプチャしたビデオはCALayer
のサブクラスであるAVCaptureVideoPreviewLayer
で表示することができるので、それをプロパティに持ちます。
struct CaptureView: View {
var body: some View {
ZStack {
CALayerView(caLayer: AVCaptureVideoPreviewLayer)
}
}
}
次に、カメラ制御を責務とする AVFoundationManager
を用意しました。
このクラスでは、AVCaptureDevice
や AVCaptureSession
クラスを使用してカメラの設定や制御を行ったりします。CALayerView
に渡す必要があるAVCaptureVideoPreviewLayer
はCaptureSession組み合わせた状態である必要があるので、このクラスで生成されます。詳細
そうすると、以下のような実装になってくると思います。
struct CaptureView: View {
var avFoundationManager: AVFoundationManager
var body: some View {
ZStack {
CALayerView(caLayer: avFoundationManager.previewLayer)
}
.onAppear {
avFoundationManager.startSession()
}
.onDisappear {
avFoundationManager.endSession()
}
}
}
これでカメラが起動した画面は表示されます📷
が、
TCAを使用する場合、AVFoundationManager
をEnvironmentにもたせて、Reducerでカメラの起動を扱うこともべき? とか考え始めました。
ただこの場合、avFoundationManager.previewLayer
をStateとして扱う必要がでてきます。
大体こんな感じ。
struct CaptureEnvironment {
var avFoundationManager : AVFoundationManager
}
let captureReducer = Reducer<CaptureState, CaptureAction, CaptureEnvironment> {
state, action, environment in
switch action {
case let .onAppear:
environment.avFoundationManager.startSession()
state.previewLayer = avFoundationManager.previewLayer
return .none
case .onDisappear:
environment.avFoundationManager.endSession()
return .none
}
}
まとめ
冒頭でもお伝えした通り、気になっているポイントとしては
- カメラのセッション開始や終了はReducerで扱うべきか
- ViewをStateとして扱うことに違和感を感じないか
の二つになります。
私ははじめ、カメラのセッション開始や終了はReducerで扱う形で実装していました。
ですが、View自体をStateとして扱うことに違和感があったり、要件的にカメラ状態はViewの生存と一蓮托生なのでReducerで扱う必要ないんじゃないかとかいろいろ悩んでいる、なうです。
いいアイディアや、ご意見ご感想、お待ちしています🙏