Использование environmentObject в watchOS

Я пытаюсь использовать environmentObject в приложении watchOS6, чтобы связать мою модель данных с моим представлением.

Я создал простое, автономное приложение Watch в Xcode 11.

Я создал новый 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?

1 ответ

Решение

Вы можете использовать стирание типа, AnyView в случае SwiftUI View,

Я бы рефакторинг WKHostingController вернуться AnyView,

Кажется, это хорошо с моей стороны.

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

Для всех, кто, как Бретт (в комментариях), получал

"Property 'body' with type 'AnyView' cannot override a property with type 'ContentView'"

Я получил ту же ошибку, потому что я не заменил возвращаемое значение и не обернул возвращаемый ContentView.

т.е. так выглядела моя первая попытка... обратите внимание на WKHostingController<ContentView>которые должны бытьWKHostingController<AnyView>

class HostingController : WKHostingController<ContentView> {
    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
    }
}
Другие вопросы по тегам