无法在控制器中获取@EnvironmentObject

回转器

我正在尝试使用@EnvironmentObject来控制我的应用程序的某些方面。我遇到的问题是我的一个控制器无法访问环境对象。我收到致命错误“找不到类型为Environment的@ObservableObject”。

我搜索了其他问题,发现的每个解决方案都包括发送.environmentObject(myEnvironment)到有问题的视图。问题是这不是一个视图,而且我似乎没有那个选择。

另外,在我的SceneDelegate中,我将environmentObject发送到第一个视图,所以这不是问题。

这是我的代码。

首先,我创建了一个模型来声明所有环境变量

环境

struct Environment {
        var showMenu: Bool
        var searchText: String
        var location : Location

        init() {
            self.showMenu = false
            self.searchText = ""
            self.location = Location()
        }
    }

接下来,我有一个控制器,其目的是处理与环境有关的任何操作,现在它没有任何控制器

环境控制器

import Foundation

class EnvironmentController : ObservableObject {
    @Published var environment = Environment()
}

现在,在SceneDelegate中,我调用NextDeparturesView,后者依次调用MapView。

MapView

import SwiftUI
import MapKit

//MARK: Map View
struct MapView : UIViewRepresentable {

    @EnvironmentObject var environmentController: EnvironmentController
    var locationController = LocationController()

    func makeUIView(context: Context) -> MKMapView {
        MKMapView(frame: .zero)
    }

    func updateUIView(_ uiView: MKMapView, context: Context) {
        let coordinate = CLLocationCoordinate2D(
            latitude: environmentController.environment.location.latitude,
            longitude: environmentController.environment.location.longitude)
        let span = MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1)
        let region = MKCoordinateRegion(center: coordinate, span: span)
        uiView.showsUserLocation = true
        uiView.setRegion(region, animated: true)
    }
}

您会注意到,在MapView中,我称为LocationController,这是发生致命错误的地方

LocationController

import SwiftUI
import MapKit
import CoreLocation

final class LocationController: NSObject, CLLocationManagerDelegate, ObservableObject {
    //MARK: Vars
    @EnvironmentObject var environmentController: EnvironmentController
    @ObservedObject var userSettingsController = UserSettingsController()

    //var declaration - Irrelevant code to the question

    //MARK: Location Manager
    var locationManager = CLLocationManager()

    //MARK: Init
    override init() {
        //more irrelevant code

        super.init()

        //Ask for location access
        self.updateLocation()
    }

    //MARK: Functions
    func updateLocation() {
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        if locationManager.responds(to: #selector(CLLocationManager.requestAlwaysAuthorization)){
            locationManager.requestAlwaysAuthorization()
        }
        else {
            locationManager.startUpdatingLocation()
        }
    }

    //MARK: CLLocationManagerDelegate methods
    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        print("Error updating location :%@", error)
    }

    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        switch status {
        case .notDetermined:
            self.setDefaultLocation()
            break
        case .restricted:
            self.setDefaultLocation()
            break
        case .denied:
            self.setDefaultLocation()
            break
        default:
            locationManager.startUpdatingLocation()
        }
    }

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {

        let currentLocation = manager.location?.coordinate
        self.environmentController.environment.location.latitude = Double(currentLocation!.latitude)
        self.environmentController.environment.location.longitude = Double(currentLocation!.longitude)

        manager.stopUpdatingLocation()
    }

    //MARK: Other Functions

    func recenter() {
        locationManager.startUpdatingLocation()
    }

    func setDefaultLocation() {
        if self.$userSettingsController.userCity.wrappedValue == "" {
            self.environmentController.environment.location.latitude = 0.0
            self.environmentController.environment.location.longitude = 0.0          
        } else {
            self.environmentController.environment.location.latitude = self.citiesDictionary[self.userSettingsController.userCity]!.latitude
            self.environmentController.environment.location.longitude = self.citiesDictionary[self.userSettingsController.userCity]!.longitude       
        }
    }
}

因此,这是发生致命错误的地方。例如,我的应用程序通常会setDefaultLocation()调用,而应用程序在那里崩溃。知道我做错了什么,或者如何解决?

先感谢您。

编辑

经过@ pawello2222的大量帮助后,我已经解决了我的问题,但是对我的应用程序的整体结构进行了一些更改。

我会接受他的答案是正确的,但是我会提供一份我所做的事情的清单,以便将来看到此问题的人可能会朝着正确的方向前进。

  1. 我错误地假设ViewUIViewRepresentable可能两个访问@EnvironmentObject只能View
  2. 在我的Environment结构中,Location我现在有了一个,而不是一个var LocationController,因此在整个应用程序中使用了相同的实例。在我的LocationController我现在有一个@Published var location: Location,所以每一个视图可以访问相同的位置。
  3. 在类型的结构中,View我创建@EnvironmentObject var environmentController: EnvironmentController并使用LocationController与之关联的结构。在其他类类型中,我只是有一个init接收方法,例如,当我调用I doLocationController,该方法是通过发送的从而确保它与整个应用程序中使用的控制器相同,并且被更改。在诸如之类的类中使用很重要,否则将不会检测到更改。environmentControllerMapViewMapView(locController: environmentController.environment.locationController)Location@ObservedObject var locationController: LocationControllerMapView

希望这可以帮助。

pawello2222

请勿@EnvironmentObjectController/中使用ViewModel(实际上是在之外的任何地方View)。如果要观察Controller中环境的变化,可以执行以下操作:

class Environment: ObservableObject {
    @Published var showMenu: Bool = false
    @Published var searchText: String = ""
    @Published var location : Location = Location()
}
class Controller: ObservableObject {
    @Published var showMenu: Bool

    private var environment: Environment
    private var cancellables = Set<AnyCancellable>()

    init(environment: Environment) {
        _showMenu = .init(initialValue: environment.showMenu)
        environment.$showMenu
            .receive(on: DispatchQueue.main)
            .sink(receiveValue: { [weak self] value in
                self?.showMenu = value
            })
            .store(in: &cancellables)
    }
}

您还可以使用其他形式的依赖项注入来注入Environment(甚至使用单例)。


通常,有多种方法可以在视图中显示Environment变量(例如showMenu)(并刷新):

1)在您需要唯一访问的情况下,将-作为-Environment注入到您的ViewNOT to ViewModel)中@EnvironmentObjectEnvironmentView

2)ViewModel订阅Environment(如上所述)并将其自己的变量发布到View无需使用@EnvironmentObject在你View呢。

3)作为Environment注入您View的中@EnvironmentObject,然后传递给ViewModel

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

无法在控制器中获取ID

来自分类Dev

无法从服务获取控制器中的数据

来自分类Dev

我无法从ExtJS的控制器中获取组件

来自分类Dev

为什么我无法在控制器中获取参数?

来自分类Dev

无法访问控制器中的获取变量

来自分类Dev

无法从复选框中的控制器获取标签

来自分类Dev

无法在父控制器中获取 Partialview 模型

来自分类Dev

无法从控制器中的 HTTP 方法获取回调

来自分类Dev

Angular控制器无法获取“ this”

来自分类Dev

在控制器中获取环境值

来自分类Dev

从控制器中的URL获取协议

来自分类Dev

在控制器中获取视图

来自分类Dev

在控制器中获取ActiveModel :: ForbiddenAttributesError

来自分类Dev

在控制器中获取特定信息?

来自分类Dev

在控制器中获取空值

来自分类Dev

从控制器中的数组获取值

来自分类Dev

在控制器中获取ApplicationUser对象

来自分类Dev

在Ember中获取模型的控制器

来自分类Dev

无法从mvc获取控制器方法(来自Uri())中的QueryString获取DATETIME

来自分类Dev

无法从mvc获取控制器方法(来自Uri())中的QueryString获取DATETIME

来自分类Dev

在 MVC5 中回发后无法获取控制器中按钮的值

来自分类Dev

如何从控制器中获取配置(从控制器中获取配置)?

来自分类Dev

无法在Codeigniter中从模型到控制器获取整个数据值

来自分类Dev

在Magento控制器中,无法获取在此操作上重定向之前设置的会话变量

来自分类Dev

我无法在控制器中发布的文本框中获取值

来自分类Dev

无法从AngularJS中的控制器初始化和获取数组

来自分类Dev

使用ajax提交表单时,无法从视图中获取控制器中的字段数据

来自分类Dev

嵌套视图无法从Laravel 5.1中的父控制器获取数据

来自分类Dev

无法获取Lamar(IOC)来解析.NET Core 3.1中的API控制器依赖项

Related 相关文章

  1. 1

    无法在控制器中获取ID

  2. 2

    无法从服务获取控制器中的数据

  3. 3

    我无法从ExtJS的控制器中获取组件

  4. 4

    为什么我无法在控制器中获取参数?

  5. 5

    无法访问控制器中的获取变量

  6. 6

    无法从复选框中的控制器获取标签

  7. 7

    无法在父控制器中获取 Partialview 模型

  8. 8

    无法从控制器中的 HTTP 方法获取回调

  9. 9

    Angular控制器无法获取“ this”

  10. 10

    在控制器中获取环境值

  11. 11

    从控制器中的URL获取协议

  12. 12

    在控制器中获取视图

  13. 13

    在控制器中获取ActiveModel :: ForbiddenAttributesError

  14. 14

    在控制器中获取特定信息?

  15. 15

    在控制器中获取空值

  16. 16

    从控制器中的数组获取值

  17. 17

    在控制器中获取ApplicationUser对象

  18. 18

    在Ember中获取模型的控制器

  19. 19

    无法从mvc获取控制器方法(来自Uri())中的QueryString获取DATETIME

  20. 20

    无法从mvc获取控制器方法(来自Uri())中的QueryString获取DATETIME

  21. 21

    在 MVC5 中回发后无法获取控制器中按钮的值

  22. 22

    如何从控制器中获取配置(从控制器中获取配置)?

  23. 23

    无法在Codeigniter中从模型到控制器获取整个数据值

  24. 24

    在Magento控制器中,无法获取在此操作上重定向之前设置的会话变量

  25. 25

    我无法在控制器中发布的文本框中获取值

  26. 26

    无法从AngularJS中的控制器初始化和获取数组

  27. 27

    使用ajax提交表单时,无法从视图中获取控制器中的字段数据

  28. 28

    嵌套视图无法从Laravel 5.1中的父控制器获取数据

  29. 29

    无法获取Lamar(IOC)来解析.NET Core 3.1中的API控制器依赖项

热门标签

归档