我在源代码中使用了@EnvironmentObject,但无法正常工作。
这只是我的代码
import Foundation
import MapKit
class Configure: ObservableObject
{
@Published var mapType = MKMapType.satellite
}
我在userData中有Configure对象:
class UserData: ObservableObject
{
@Published var configure: Configure
}
并使用MapHome中的configure对象:
struct MapHome: View
{
@EnvironmentObject var userData: UserData
NavigationView
{
ZStack
{
MapView(mapViewState: mapViewHomeState)
.edgesIgnoringSafeArea(.all)
}
Button(action: {
switch self.userData.configure.mapType
{
case .hybrid:
self.userData.configure.mapType = .standard
case .standard:
self.userData.configure.mapType = .satellite
case .satellite:
self.userData.configure.mapType = .hybrid
default:
self.userData.configure.mapType = .standard
}
}
)
{
if self.configure.mapType == .hybrid
{
Image("HybridIcon")
}
else if self.configure.mapType == .standard
{
Image("StandardIcon")
}
else if self.configure.mapType == .satellite
{
Image("SatelliteIcon")
}
}
}
}
MapView就是这样:
import SwiftUI
import MapKit
struct MapView: UIViewRepresentable
{
@ObservedObject var configure: Configure
func makeUIView(context: Context) -> MKMapView
{
return MKMapView(frame: .zero)
}
func updateUIView(_ view: MKMapView, context: Context)
{
//Set the map type
view.mapType = configure.mapType
}
}
当我单击按钮时,源代码已转到MapView(mapViewState:mapViewHomeState).edgesIgnoringSafeArea(.all),但未调用MapView.updateUIView!因此,地图视图不会使用MKMapType刷新!
我的代码有什么问题?我该怎么办? 非常感谢!
答案 0 :(得分:0)
如@SorinLica在评论中所述,此时Nested ObservableObjects
don't work in SwiftUI。
最简单的方法可能是将Configure
对象直接添加到环境中(这是一个类,因此它将与UserData
实例所引用的实例相同)。
在您的SceneDelegate
中-
let userData = UserData()
let contentView = MapHome().environmentObject(userData).environmentObject(userData.configure)
然后您可以在MapHome
struct MapHome: View
{
@EnvironmentObject var userData: UserData
@EnvironmentObject var configure: Configure
NavigationView
{
ZStack
{
MapView(mapViewState: $configure.mapType)
.edgesIgnoringSafeArea(.all)
}
Button(action: {
switch self.userData.configure.mapType
{
case .hybrid:
self.userData.configure.mapType = .standard
case .standard:
self.userData.configure.mapType = .satellite
case .satellite:
self.userData.configure.mapType = .hybrid
default:
self.userData.configure.mapType = .standard
}
}
)
{
if self.userData.configure.mapType == .hybrid
{
Image("HybridIcon")
}
else if self.userData.configure.mapType == .standard
{
Image("StandardIcon")
}
else if self.userData.configure.mapType == .satellite
{
Image("SatelliteIcon")
}
}
}
}
您的MapView
将需要mapType
作为@Binding
-
struct MapView: UIViewRepresentable
{
@Binding var mapType: MKMapType
func makeUIView(context: Context) -> MKMapView
{
return MKMapView(frame: .zero)
}
func updateUIView(_ view: MKMapView, context: Context)
{
//Set the map type
view.mapType = mapType
}
}
另一种方法是将地图类型镜像到@State
中的MapHome
属性
struct MapHome: View
{
@EnvironmentObject var userData: UserData
@State var mapType: MKMapType
NavigationView
{
ZStack
{
MapView(mapViewState: $mapType)
.edgesIgnoringSafeArea(.all)
}
Button(action: {
switch self.userData.configure.mapType
{
case .hybrid:
self.userData.configure.mapType = .standard
case .standard:
self.userData.configure.mapType = .satellite
case .satellite:
self.userData.configure.mapType = .hybrid
default:
self.userData.configure.mapType = .standard
}
self.mapType = self.userdata.configure.mapType
}
)
{
if self.userdata.configure.mapType == .hybrid
{
Image("HybridIcon")
}
else if self.userdata.configure.mapType == .standard
{
Image("StandardIcon")
}
else if self.userdata.configure.mapType == .satellite
{
Image("SatelliteIcon")
}
}
}
}
您需要在SceneDelegate
let userData = UserData()
let contentView = MapHome(mapType: userData.configure.mapType).environmentObject(userData)
答案 1 :(得分:-1)
您在哪里分配环境对象?
通常,您会这样:
MapHome().environmentObject(UserData())
答案 2 :(得分:-1)
您需要在SceneDelegate.swift文件中分配环境对象,并且该对象可以从整个层次结构访问。 应该看起来像这样:
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use a UIHostingController as window root view controller
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: MapHome().environmentObject(UserData())
self.window = window
window.makeKeyAndVisible()
}
}