1

I've seen similar questions on this but none that are up to date or work successfully, I've followed Apples Developer docs, various videos, and guides on how to do this but it still throws these warnings

2023-01-11 11:33:16.044044-0500 Walkman[50986:4824621] [SwiftUI] Publishing changes from within view updates is not allowed, this will cause undefined behavior.

It feels like I've tried everything from onChange() to @StateObject instead of @ObservedObject... It's those few lines because the warnings go away if the Map gets commented out.

The code that's causing the error is the

struct OrderView: View {
    @ObservedObject var cartManager: CartManager
//    @ObservedObject var locationManager: LocationManager
    
    @EnvironmentObject var locationManager: LocationManager
    @EnvironmentObject var viewModel: AppViewModel
    @State private var tracking:MapUserTrackingMode = .follow
    @State private var driversIn: Bool = false
    
    var body: some View {
        NavigationView {
//            Text("Testing")
            Map(
                coordinateRegion: $locationManager.region,
                interactionModes: MapInteractionModes.all,
                showsUserLocation: true,
                userTrackingMode: $tracking,
                annotationItems: locationManager.MapLocations,
                annotationContent: { item in
                    MapMarker(coordinate: item.coordinate, tint: .red)
//                    MapAnnotation(coordinate: item.location) {
//                        Rectangle()
//                            .stroke(Color.purple, lineWidth: 3)
//                            .frame(width: 10, height: 10)
//                    }
                }
            )
            .navigationTitle("Orders")

            .onAppear {
                locationManager.getNearbyDrivers(query: GeoQuery(distance: 400, geo: locationManager.createGeo()))
            }
            .ignoresSafeArea()
//            .onReceive(locationManager.$drivers, perform: { drivers in
////                print("DEBUG: DRIVERS _ \(drivers)")
//                for driver in drivers {
//                    print("DEBUG: DRIVER TEST _ \(driver)")
//                    locationManager.MapLocations.append(MapLocation(id: driver.id, name: driver.name, latitude: driver.location.coordinates[0], longitude: driver.location.coordinates[1]))
//                }
//            })
        }
        
        
    }
}

Here is my LocationManager

final class LocationManager: NSObject, CLLocationManagerDelegate, ObservableObject {
    @Published var region = MKCoordinateRegion(center: MapDetails.startingLocation, span: MapDetails.defaultSpan)
    @Published var authorizationStatus: CLAuthorizationStatus?
    @Published var location: CLLocation?
    @Published var MapLocations = [MapLocation]()
    
    @Published var drivers = [Driver]()
    var locationManager = CLLocationManager()
    
    override init() {
        super.init()
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.requestWhenInUseAuthorization()
        
    }
    
    func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
        switch manager.authorizationStatus {
        case .authorizedWhenInUse:
            authorizationStatus = .authorizedWhenInUse
            manager.startUpdatingLocation()
            break
        case .restricted, .denied:
            authorizationStatus = .restricted
            manager.stopUpdatingLocation()
            break
        case .notDetermined:
            authorizationStatus = .notDetermined
            manager.requestWhenInUseAuthorization()
            break
        default:
            break
        }
    }
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        guard let location = locations.last else { return }
        DispatchQueue.main.async {
            self.location = location
//            self.MapLocations.append(MapLocation(name: "1", latitude: location.coordinate.latitude, longitude: location.coordinate.longitude))
            // MARK - API for location calls, send when users location updates
            print("DEBUG: Location: \(self.location?.coordinate.longitude ?? 0.00)")
        }
    }
    
    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        print("DEBUG: \(error.localizedDescription)")
    }
    
    func createGeo() -> GeoJSON {
        return GeoJSON(coordinates: [locationManager.location?.coordinate.latitude ?? 0.00, locationManager.location?.coordinate.longitude ?? 0.00])
    }

    
    func getNearbyDrivers(query: GeoQuery) {
        guard let url = URL(string: "http://localhost:8000/drivers-nearby") else { fatalError("Missing URL") }
        
        var request = URLRequest(url: url)
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        request.httpMethod = "POST"
        let payload: [String: Any] = [
            "distance": query.distance,
            "geo": ["type": "Point", "coordinates": query.geo.coordinates]
        ]
        let data = try! JSONSerialization.data(withJSONObject: payload, options: [])
        request.httpBody = data

        let dataTask = URLSession.shared.dataTask(with: request) { (data, response, error) in
            if let error = error {
                print("Request error: ", error)
                return
            }
            guard let response = response as? HTTPURLResponse else { return }
            
            if response.statusCode == 200 {
                guard let data = data else { return }
                DispatchQueue.main.async {
                    do {
                        let drivers = try JSONDecoder().decode([Driver].self, from: data)
                        
                        print("DEBUG: Drivers: \(drivers)")
                        self.drivers = drivers
                        for driver in self.drivers {
                            let location = MapLocation(id: driver.id, name: driver.name, latitude: driver.location.coordinates[0], longitude: driver.location.coordinates[1])
                            var driverIsVisible: Bool {
                                return self.MapLocations.contains(where: { annotation in
                                    guard var driverAnno = annotation as? MapLocation else { return false }
                                    print("DEBUG: cast driverAnno | driverAnno \(driverAnno.id) | driver \(driver.id)")
                                    if driverAnno.id == driver.id {
                                        print("DEBUG: Handle update driver position")
                                        driverAnno.latitude = driver.location.coordinates[0]
                                        driverAnno.longitude = driver.location.coordinates[1]
                                        return true
                                    }
                                    return false
                                })
                            }
                            
                            if !driverIsVisible {
                                print("DEBUG: Inserting map annotation \(location.id)")
                                self.MapLocations.append(location)
                            }
                        }
                        
                    } catch let error {
                        print("Error decoding: ", error)
                    
                    }
                }
            }
        }
        
        dataTask.resume()
    }
    

    
////    private func geocode() {
////        guard let location = self.location else { return }
////        geocoder.reverseGeocodeLocation(location) { (places, error) in
////            if error == nil {
////                self.placemark = places?[0]
////            } else {
////                self.placemark = nil
////            }
////        }
////    }
}

1 Answers1

-1

Removing @Published from region in LocationManager will fix this warning.

  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jan 17 '23 at 20:12
  • Removing the `@published` will prevent the region being updated as the user moves the map around. It also doesn't remove the warnings. – CW0007007 Jun 08 '23 at 12:46