web-dev-qa-db-ja.com

watchOSでのenvironmentObjectの使用

データモデルをビューにバインドするために、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ビューに注入する他の方法はありますか?

18
Paulw11

SwiftUI AnyViewの場合、型消去、Viewを使用できます。

WKHostingControllerをリファクタリングしてAnyViewを返します。

これは私の側でうまくコンパイルされているようです。

class HostingController : WKHostingController<AnyView> {
    override var body: AnyView {
        return AnyView(ContentView().environmentObject(DataModel()))
    }
}
38
Matteo Pacini

マッテオの素晴らしい答えに加えて、

デリゲートを使用する場合は、次のように使用します。

class HostingController : WKHostingController<AnyView> {
    override var body: AnyView {
        var contentView = ContentView()
        contentView.environmentObject(DataModel())
        contentView.delegate = self
        let contentWrapperView = AnyView(contentView)
        return contentWrapperView
    }
}
0
Zaid Pathan