@EnvironmentObject没有反映在对象中

时间:2019-10-21 02:11:35

标签: ios swift swiftui

我在源代码中使用了@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刷新!

我的代码有什么问题?我该怎么办? 非常感谢!

3 个答案:

答案 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()
    }
}