データモデルをビューにバインドするために、watchOS6アプリでenvironmentObject
を使用しようとしています。
Xcode 11でシンプルなスタンドアロンのWatchアプリを作成しました。
新しいDataModel
クラスを作成しました
import Combine
import Foundation
import SwiftUI
final class DataModel: BindableObject {
let didChange = PassthroughSubject<DataModel,Never>()
var aString: String = "" {
didSet {
didChange.send(self)
}
}
}
私のContentView
構造体で、@EnvironmentObject
を使用してこのクラスをバインドします-
struct ContentView : View {
@EnvironmentObject private var dataModel: DataModel
var body: some View {
Text($dataModel.aString.value)
}
}
最後に、DataModel
のインスタンスをHostingController
クラスの環境に挿入しようとしています-
class HostingController : WKHostingController<ContentView> {
override var body: ContentView {
return ContentView().environmentObject(DataModel())
}
}
しかし、エラーが発生します:
Cannot convert return expression of type '_ModifiedContent<ContentView, _EnvironmentKeyWritingModifier<DataModel?>>' to return type 'ContentView'
エラーは、WKHostingController
が具象型(この場合はWKHostingController<ContentView>
)を必要とするジェネリックであるためです。
UIHostingController
はジェネリッククラスではないため、iOSアプリのUIHostingController
でも同様のアプローチが完全に機能します。
環境をwatchOSビューに注入する他の方法はありますか?
SwiftUI AnyView
の場合、型消去、View
を使用できます。
WKHostingController
をリファクタリングしてAnyView
を返します。
これは私の側でうまくコンパイルされているようです。
class HostingController : WKHostingController<AnyView> {
override var body: AnyView {
return AnyView(ContentView().environmentObject(DataModel()))
}
}
マッテオの素晴らしい答えに加えて、
デリゲートを使用する場合は、次のように使用します。
class HostingController : WKHostingController<AnyView> {
override var body: AnyView {
var contentView = ContentView()
contentView.environmentObject(DataModel())
contentView.delegate = self
let contentWrapperView = AnyView(contentView)
return contentWrapperView
}
}