gpt4 book ai didi

ios - 无法在 Controller 中获取@EnvironmentObject

转载 作者:行者123 更新时间:2023-12-01 21:46:08 24 4
gpt4 key购买 nike

我正在尝试使用 @EnvironmentObject 来控制我的应用程序的某些方面。我遇到的问题是我的一个 Controller 无法访问环境对象。我收到 fatal error “未找到环境类型的 @ObservableObject”。

我搜索了其他问题,我能找到的每个解决方案都包括发送 .environmentObject(myEnvironment)到有问题的观点。问题是这不是一个 View ,我似乎没有那个选项。

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

这是我的代码。

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

环境

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

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

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

环境 Controller
import Foundation

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

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

map 查看
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,这是发生 fatal error 的地方

位置 Controller
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
}
}
}

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

先感谢您。

编辑

在@pawello2222 的大力帮助下,我解决了我的问题,但是对我的应用程序的整体结构进行了一些更改。

我会接受他的回答作为正确的答案,但我会提供一份我做过的事情的 list ,所以将来看到这个的任何人都可能会被推向正确的方向。
  • 我错误地假设 ViewUIViewRepresentable都可以访问 @EnvironmentObject .仅限 View能够。
  • 在我的 Environment结构,而不是 Location var,我现在有一个 LocationController ,因此在整个应用程序中使用相同的实例。在我的 LocationController我现在有一个 @Published var location: Location ,因此每个 View 都可以访问相同的位置。
  • View 类型的结构中我创建了 @EnvironmentObject var environmentController: EnvironmentController并使用 LocationController与之相关联。在其他类类型中,我只有一个 init接收 LocationController 的方法,通过 environmentController 发送,例如,当我调用 MapView我愿意:MapView(locController: environmentController.environment.locationController)从而确保它是整个应用程序中使用的相同 Controller 和相同的 Location正在改变。重要的是使用 @ObservedObject var locationController: LocationController在诸如 MapView 之类的类中,否则不会检测到更改。

  • 希望这可以帮助。

    最佳答案

    不要使用 @EnvironmentObject在您的 Controller/ViewModel (实际上是在 View 之外的任何地方)。如果你想观察 Controller 中 Environment 的变化,你可以这样做:

    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)
    }
    }

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

    通常有不同的方式来显示您的 Environment View 中的变量(例如 showMenu )(并刷新它):

    1) Environment注入(inject)您的 View ( 不是 ViewModel )作为 @EnvironmentObject - 适用于需要访问 Environment 的情况来自 View只要。

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

    3) Environment注入(inject)您的 View作为 @EnvironmentObject然后传递给 ViewModel .

    关于ios - 无法在 Controller 中获取@EnvironmentObject,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62205556/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com