Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 如何从UIRepresentable MapView访问底层GMSMapView_Swift_Google Maps_Swiftui - Fatal编程技术网

Swift 如何从UIRepresentable MapView访问底层GMSMapView

Swift 如何从UIRepresentable MapView访问底层GMSMapView,swift,google-maps,swiftui,Swift,Google Maps,Swiftui,在我的应用程序中,我有一个ViewModel(MapViewModel)类、一个UIRepresentable类和ContentView。我正在寻找一种方法来访问作为UIRepresentable类创建的ViewModel中的GMSMapView视图 ContentView.swift: import SwiftUI import Combine struct ContentView: View { @State private var selection = 0 @State

在我的应用程序中,我有一个ViewModel(MapViewModel)类、一个UIRepresentable类和ContentView。我正在寻找一种方法来访问作为UIRepresentable类创建的ViewModel中的GMSMapView视图

ContentView.swift:

import SwiftUI
import Combine

struct ContentView: View {
    @State private var selection = 0
    @State private var dragOffset = CGSize.zero
    @ObservedObject var mapViewModel : MapViewModel = MapViewModel()

    var body: some View {
        GeometryReader { geo in
            TabView(selection: self.$selection) {
                MapView()
                    .edgesIgnoringSafeArea(.all)
                    .tabItem {
                        VStack {
                            Image(systemName: "house")
                            Text("Home")
                        }
                }
                .tag(0)

                Text("Second Page")

                    .tabItem {
                        VStack {
                            Image(systemName: "gear")
                            Text("Settings")
                        }
                }
                .tag(1)

                Text("Third Page")

                    .tabItem {
                        VStack {
                            Image(systemName: "gear")
                            Text("Third Page")
                        }
                }
                .tag(2)
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

import UIKit
import SwiftUI
import GoogleMaps

struct MapView: UIViewRepresentable {

    func makeUIView(context: Context) -> GMSMapView {

        let camera = GMSCameraPosition.camera(withLatitude: 30.267153, longitude: -97.7430608, zoom: 6.0)
        let gmsMapView = GMSMapView.map(withFrame: CGRect.zero, camera: camera)
        gmsMapView.delegate = context.coordinator
        return gmsMapView
    }

    func updateUIView(_ mapView: GMSMapView, context: Self.Context) {

    }

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    class Coordinator: NSObject, GMSMapViewDelegate {
        var parent: MapView

        init(_ parent: MapView) {
            self.parent = parent
        }       
    }
}

struct GoogleMapView_Previews: PreviewProvider {
    static var previews: some View {
        MapView()
    }
}
struct ContentView: View {
    @State private var selection = 0
    @State private var dragOffset = CGSize.zero
    @ObservedObject var mapViewModel: MapViewModel

    var body: some View {
        GeometryReader { geo in
            TabView(selection: self.$selection) {
                MapView()
                    .edgesIgnoringSafeArea(.all)
                    .tabItem {
                        VStack {
                            Image(systemName: "house")
                            Text("Home")
                        }
                }
                .tag(0)

                Text("Second Page")

                    .tabItem {
                        VStack {
                            Image(systemName: "gear")
                            Text("Settings")
                        }
                }
                .tag(1)

                Text("Third Page")

                    .tabItem {
                        VStack {
                            Image(systemName: "gear")
                            Text("Third Page")
                        }
                }
                .tag(2)
            }
        }
    }
}
MapViewModel.swift:

import Foundation
import Combine
import GoogleMaps
import os

class MapViewModel: NSObject, ObservableObject {

    let lm = CLLocationManager()
    var myLocations =  [CLLocation]()


    override init() {

        super.init()

        lm.delegate = self
        lm.desiredAccuracy = kCLLocationAccuracyBest
        lm.requestWhenInUseAuthorization()
        lm.pausesLocationUpdatesAutomatically = false
        lm.allowsBackgroundLocationUpdates = true
        lm.startUpdatingLocation()

    }

}

extension MapViewModel: CLLocationManagerDelegate {

    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        //self.status = status

    }

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

        os_log("locationManager:didUpdateLocations: received location",log: Log.general, type: .debug)
    }
}

MapView.swift:

import SwiftUI
import Combine

struct ContentView: View {
    @State private var selection = 0
    @State private var dragOffset = CGSize.zero
    @ObservedObject var mapViewModel : MapViewModel = MapViewModel()

    var body: some View {
        GeometryReader { geo in
            TabView(selection: self.$selection) {
                MapView()
                    .edgesIgnoringSafeArea(.all)
                    .tabItem {
                        VStack {
                            Image(systemName: "house")
                            Text("Home")
                        }
                }
                .tag(0)

                Text("Second Page")

                    .tabItem {
                        VStack {
                            Image(systemName: "gear")
                            Text("Settings")
                        }
                }
                .tag(1)

                Text("Third Page")

                    .tabItem {
                        VStack {
                            Image(systemName: "gear")
                            Text("Third Page")
                        }
                }
                .tag(2)
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

import UIKit
import SwiftUI
import GoogleMaps

struct MapView: UIViewRepresentable {

    func makeUIView(context: Context) -> GMSMapView {

        let camera = GMSCameraPosition.camera(withLatitude: 30.267153, longitude: -97.7430608, zoom: 6.0)
        let gmsMapView = GMSMapView.map(withFrame: CGRect.zero, camera: camera)
        gmsMapView.delegate = context.coordinator
        return gmsMapView
    }

    func updateUIView(_ mapView: GMSMapView, context: Self.Context) {

    }

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    class Coordinator: NSObject, GMSMapViewDelegate {
        var parent: MapView

        init(_ parent: MapView) {
            self.parent = parent
        }       
    }
}

struct GoogleMapView_Previews: PreviewProvider {
    static var previews: some View {
        MapView()
    }
}
struct ContentView: View {
    @State private var selection = 0
    @State private var dragOffset = CGSize.zero
    @ObservedObject var mapViewModel: MapViewModel

    var body: some View {
        GeometryReader { geo in
            TabView(selection: self.$selection) {
                MapView()
                    .edgesIgnoringSafeArea(.all)
                    .tabItem {
                        VStack {
                            Image(systemName: "house")
                            Text("Home")
                        }
                }
                .tag(0)

                Text("Second Page")

                    .tabItem {
                        VStack {
                            Image(systemName: "gear")
                            Text("Settings")
                        }
                }
                .tag(1)

                Text("Third Page")

                    .tabItem {
                        VStack {
                            Image(systemName: "gear")
                            Text("Third Page")
                        }
                }
                .tag(2)
            }
        }
    }
}

我想知道如何在MapViewModel中访问gmsMapView对象。我需要在地图上画线…谢谢

通过将多段线值定义为@Published并通过updateUI中的viewmodel访问它,我能够克服这个问题。因此,我没有尝试从viewmodel访问mapview,而是让视图添加多段线覆盖。希望这对其他人有帮助。谢谢

ContentView.swift:

import SwiftUI
import Combine

struct ContentView: View {
    @State private var selection = 0
    @State private var dragOffset = CGSize.zero
    @ObservedObject var mapViewModel : MapViewModel = MapViewModel()

    var body: some View {
        GeometryReader { geo in
            TabView(selection: self.$selection) {
                MapView()
                    .edgesIgnoringSafeArea(.all)
                    .tabItem {
                        VStack {
                            Image(systemName: "house")
                            Text("Home")
                        }
                }
                .tag(0)

                Text("Second Page")

                    .tabItem {
                        VStack {
                            Image(systemName: "gear")
                            Text("Settings")
                        }
                }
                .tag(1)

                Text("Third Page")

                    .tabItem {
                        VStack {
                            Image(systemName: "gear")
                            Text("Third Page")
                        }
                }
                .tag(2)
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

import UIKit
import SwiftUI
import GoogleMaps

struct MapView: UIViewRepresentable {

    func makeUIView(context: Context) -> GMSMapView {

        let camera = GMSCameraPosition.camera(withLatitude: 30.267153, longitude: -97.7430608, zoom: 6.0)
        let gmsMapView = GMSMapView.map(withFrame: CGRect.zero, camera: camera)
        gmsMapView.delegate = context.coordinator
        return gmsMapView
    }

    func updateUIView(_ mapView: GMSMapView, context: Self.Context) {

    }

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    class Coordinator: NSObject, GMSMapViewDelegate {
        var parent: MapView

        init(_ parent: MapView) {
            self.parent = parent
        }       
    }
}

struct GoogleMapView_Previews: PreviewProvider {
    static var previews: some View {
        MapView()
    }
}
struct ContentView: View {
    @State private var selection = 0
    @State private var dragOffset = CGSize.zero
    @ObservedObject var mapViewModel: MapViewModel

    var body: some View {
        GeometryReader { geo in
            TabView(selection: self.$selection) {
                MapView()
                    .edgesIgnoringSafeArea(.all)
                    .tabItem {
                        VStack {
                            Image(systemName: "house")
                            Text("Home")
                        }
                }
                .tag(0)

                Text("Second Page")

                    .tabItem {
                        VStack {
                            Image(systemName: "gear")
                            Text("Settings")
                        }
                }
                .tag(1)

                Text("Third Page")

                    .tabItem {
                        VStack {
                            Image(systemName: "gear")
                            Text("Third Page")
                        }
                }
                .tag(2)
            }
        }
    }
}
地图视图:

struct MapView: UIViewRepresentable {

    @ObservedObject var mapViewModel = MapViewModel()

    func makeUIView(context: Context) -> GMSMapView {

        let camera = GMSCameraPosition.camera(withLatitude: 30.5986015, longitude: -97.8210401, zoom: 20.0)
        let mapView = GMSMapView.map(withFrame: CGRect.zero, camera: camera)
        mapView.isMyLocationEnabled = true
        mapView.animate(toViewingAngle: 45)
        mapView.delegate = context.coordinator
        return mapView
    }

    func updateUIView(_ mapView: GMSMapView, context: Self.Context) {

        if (mapViewModel.polyline != nil) {
            print("updateUIView: Polyline = \(mapViewModel.polyline!.description)")
            os_log("updateUIView: Polyline = %{Public}s",log: Log.general, type: .debug, mapViewModel.polyline!.description)
            mapViewModel.polyline!.strokeColor = UIColor.red
            mapViewModel.polyline!.strokeWidth = 5.0
            mapViewModel.polyline!.map = mapView
        }

        if (mapViewModel.locChanged && mapViewModel.myLocations.count > 0) {

            print("updateUIView: Refocus camera on last location")
            os_log("updateUIView: Refocus camera on last location",log: Log.general, type: .debug, mapViewModel.polyline!.description)
            let camera = GMSCameraPosition.camera(withLatitude: (mapViewModel.myLocations.last?.coordinate.latitude)!, longitude: (mapViewModel.myLocations.last?.coordinate.longitude)!, zoom: 20.0)
            let _ = GMSMapView.map(withFrame: CGRect.zero, camera: camera)
        }
    }

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    class Coordinator: NSObject, GMSMapViewDelegate {
        var parent: MapView

        init(_ parent: MapView) {
            self.parent = parent
        }

    }
}
MapViewModel:

class MapViewModel: NSObject, ObservableObject {
             .
             .
             .    
    @Published var polyline: GMSPolyline?
    @Published var locChanged: Bool = false

    override init() {

        super.init()
             .
             .
             .       
        polyline = nil
    }

             .
             .
             .        
    func draw(myLocations: [CLLocation], color: UIColor) {

        os_log("MapViewController: Drawing Track for last two Locations",log: Log.general, type: .info)
        print("MapViewController: Drawing Track for last two Locations")
        let path = GMSMutablePath()
        let c1 = myLocations[myLocations.count - 1].coordinate
        let c2 = myLocations[myLocations.count - 2].coordinate
        path.add(c1)
        path.add(c2)
        polyline = GMSPolyline(path: path)
        print("draw: Polyline = \(polyline!.description)")
        polyline!.strokeColor = color
        polyline!.strokeWidth = 5.0
    }

             .
             .
             .   

extension MapViewModel: CLLocationManagerDelegate {

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

        os_log("locationManager:didUpdateLocations: received location",log: Log.general, type: .debug)

        guard let lastLocation: CLLocation = locations.last else {
            os_log("locationManager:didUpdateLocations: received null location",log: Log.general, type: .debug)
            return
        }


        if (myLocations.count >= 2) {

            os_log("MapViewController: updateLocation: Calling draw method with count = %{Public}s",log: Log.general, type: .debug, myLocations.count.description)

            self.draw(myLocations: self.myLocations, color:.red)
        }

             .
             .
             .    

        } else {

            os_log("LocationManager: Bad Location...",log: Log.general, type: .error)
            badLocationCount += 1
            locChanged = false
        }
    }
}

要在地图上绘制线覆盖(两个位置之间的线),必须将MKPolyLine或GMSPolyline添加到地图视图中。这意味着代码必须具有访问googlemap mapview或mapkit mapview的权限。一个想法是找出一种方法来告诉UIViewRepresentable视图添加覆盖,但不知道如何确保这样做。除了我之外,一定有人碰到过这个。谢谢