Hi!
First, let me introduce my current architecture (it's already there, so I have to rely on it)
I have an external objC framework VideoSDK
that allows me to load and to show various video types (for the sake of it, let's say YoutubeVideo
, DailymotionVideo
, LocalVideo
, each Video type being a totally separate objC object)
Now I created another framework (in SwiftUI) that allows me to load and show the videos from my objC framework.
In order to have a more typesafe yet flexible solution, I used a protocol based approach with some generics.
protocol VideoManager {
associatedtype Video
var video: Video { get }
init(_: Video)
func load()
func show()
var videoDelegate: Video.Delegate { get } // every lifecycle event related to the Video
var videoPublisher: VideoPublisher<Video> { get } // the same as videoDelegate but with combine for TCA
}
Now I made some custom implementations of this protocol like
struct YoutuveVideoManager: VideoManager {
typealias Video = YoutubeVideo
var video: YoutubeVideo
var videoDelegate: YoutubeVideo.Delegate
var videoPublisher: VideoPublisher<YoutubeVideo>
init(_ video: YoutubeVideo) {
self.video = video
}
func load() {
video.delegate = videoDelegate
video.load()
}
func show() {
video.show()
}
}
This allows me to create a SwiftUI view that only needs access to load()
, show()
and the delegate callbacks.
On top of that, I have a factory that returns a VideoManager
from a construct (naïve code just to show you how it's basically handled)
enum VideoType {
case youtube, dailymotion, local
}
struct VideoFactory {
func videManager<V: VideoManager>(for videoType: VideoType) -> V {
switch videoType {
case .youtube: return YoutubeVideoManager()
case .dailymotion: return DailymotionVideoManager()
case .local: return LocalVideoManager()
}
}
}
So far so ggod....
Now I wanted to introduce some TCA to handle the behind-the-scene videos.
Since I can't just initialize my AppReducer with a runtime implementation of VideoManager
, it seems that I need to inject this dependency into my reducer (I will also have to create a kind of AsyncStream ou related stuff to handle the delegate callback through the combine object like for the LiveAudioPlayer example.
But, at runtime, my View has no knowledge of the kind of implementation it is fed with (YoutubeVideoManager
, DailyMotionVideoManager
or LocalVideoManager
?). So it seems that I need to find a way to initialise my 'generic' reducer with a runtime copy of a VideoManager.
How can I achieve that ? I'm really stuck here
Thanks!