@EnvironmentObject не отражается в объекте - PullRequest
0 голосов
/ 21 октября 2019

Я использую @EnvironmentObject в моем исходном коде, но он не работает правильно.

это просто мой код:

import Foundation
import MapKit

class Configure: ObservableObject
{
    @Published var mapType = MKMapType.satellite
}

У меня есть объект Configure в userData:

class UserData: ObservableObject
{
    @Published var configure: Configure
}

И используйте объект конфигурации в MapHome:

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 голосов
/ 21 октября 2019

Вам необходимо назначить объект среды в файле 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()
    }
}
0 голосов
/ 22 октября 2019

Как упомянул @SorinLica в комментарии, в настоящее время Вложенный ObservableObjects не работает в 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)
0 голосов
/ 21 октября 2019

Где вы назначаете свой объект среды?

Как правило, вы делаете это так:

MapHome().environmentObject(UserData())
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...