Использование 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
}
}