我试图在 MKMapView 上显示 circleOverlays 但它没有显示

问题描述 投票:0回答:1

下面的代码是从数据库中获取特定数量的引用,根据一些 DBSCAN 函数给出的一些坐标制作圆覆盖,并在地图上绘制圆覆盖。每隔 10 秒,这些圆圈就会从地图中删除,并使用数据库中的相同圆圈进行更新。问题是没有显示圆圈。我试过调试这个无济于事。任何建议/帮助表示赞赏。

import MapKit
import SwiftUI
import Firebase
import FirebaseAnalytics
import FirebaseAnalyticsSwift

struct ContentView: View {
    @StateObject private var viewModel = ContentViewModel()
/* Variable region accounts for showing specific coordinate region within span, showcasing input coordinates */
    @State var annotationItems: [User] = []
    @State var locations: [CLLocation] = []
    @State var circleOverlays: [MKCircle] = []
    
    func plotUsers() {
        for i in 0...20
        {
            var latData = 0.0
            var longData = 0.0
            var userName = ""
            var userAge = 0
            var ref: DatabaseReference!

            ref = Database.database().reference().child("users").child(String(i))
            ref.getData(completion:  { error, snapshot in
                guard error == nil else {
                    print("issue")
                    return;
                }
                var a: [String: Any] = [:]
                //turning datasnapshot returned from database into a dictionary
                a = snapshot?.value as! Dictionary<String, Any>
                //assigning values from the dictionary to variables so we don't have to type all the necessary error stuff every time
                latData = (a["locData"] as? [String:Any])?["lat"] as? Double ?? -1
                longData = (a["locData"] as? [String:Any])?["long"] as? Double ?? -1
                userName = (a["name"]) as! String
                userAge = Int((a["age"] as? [String:Any])?["age"] as? String ?? "-1") ?? -5
                annotationItems.append(User(name:userName,age: userAge,latitude: latData,longitude: longData))
                self.locations.append(CLLocation(latitude: latData, longitude: longData))
            });
        }
        print("@@@@@@@@@@@@@@@@@@@@@@@Locations:@@@@@@@@@@@@@@@@@@@@@@@@",locations.count)
        
        let dbscan = DBSCAN(self.locations)
        let (sequence, places) = dbscan.findCluster(eps: 1000.0, minPts: 2)
        print("@@@@@@@@@@@@@@@@@@@@@@@Places:@@@@@@@@@@@@@@@@@@@@@@@@",places)
    
        for place in places {
            print("Cluster:", place.members.count)
            let circle = MKCircle(center: place.location.coordinate, radius: 10000)
            self.circleOverlays.append(circle)
        }
        self.viewModel.mapView.addOverlays(circleOverlays)
        print("@@@@@@@@@@@@@@@@@@@@@@@Circles:@@@@@@@@@@@@@@@@@@@@@@@@",circleOverlays)
        
    }
    
    private var timer: Timer?
    
    var body: some View {
        Map(coordinateRegion: $viewModel.region,
            showsUserLocation: true)
        .onAppear() {
//            viewModel.mapView.delegate = viewModel
            let _ = self.plotUsers()
//            let _ = self.plotUsers()
            timer?.invalidate()
            Timer.scheduledTimer(withTimeInterval: 10, repeats: true) { _ in
                let _ = self.plotUsers()
                self.locations.removeAll()
                self.viewModel.mapView.removeOverlays(circleOverlays)
                self.circleOverlays.removeAll()
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider { /* Shows map */
    static var previews: some View {
        ContentView()
    }
}

final class ContentViewModel: NSObject, ObservableObject, CLLocationManagerDelegate, MKMapViewDelegate {
    @Published var region = MKCoordinateRegion(center: CLLocationCoordinate2D(
                                                   latitude: 38.898022, longitude: -77.050604),
                                                   span: MKCoordinateSpan(
                                                   latitudeDelta: 0.05, longitudeDelta: 0.05)) /* Can substitute region coordinates with longitude,latitude from firebase */

    @Published var map = MKMapView()
    var locationManager: CLLocationManager? /* Enables location services*/
    let mapView: MKMapView!
    
    override init() {
        mapView = MKMapView()
        super.init()
        mapView.delegate = self
    }
    
    func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
        if let circleOverlay = overlay as? MKCircle {
            let circleRenderer = MKCircleRenderer(circle: circleOverlay)
            circleRenderer.fillColor = UIColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 0.3)
            circleRenderer.strokeColor = UIColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 0.7)
            circleRenderer.lineWidth = 2.0
            return circleRenderer
        }
        return MKOverlayRenderer()
    }
}

我是 Swift 的新手,所以我不完全确定 $viewModel.region 是否应该以某种方式设置为在 ContentViewModel 类中创建的 MKMapView。

swift swiftui mkmapview mkcircle
1个回答
0
投票

如果您决定走那条路,这里是带有 UIViewRepresentable 的 MKMapView。这通过将 MKCircles 添加到数组来在用户点击地图的任何地方放置一个圆圈。不完全是你要找的东西——我不确定如何合并和测试你的数据库功能——但希望这在某种程度上有助于看到一个选项:

import SwiftUI
import CoreLocation
import MapKit

struct MapTestQ2: UIViewRepresentable {
    @Binding var centerCoordinate: CLLocationCoordinate2D
    @State private var mapView = MKMapView()
    @State private var circles: [MKCircle] = []
   
    func makeUIView(context: Context) -> MKMapView {
        mapView.delegate = context.coordinator
        mapView.showsUserLocation = true
        let span = MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01)
        let region = MKCoordinateRegion(center: centerCoordinate, span: span)
        mapView.setRegion(region, animated: true)
        return mapView
    }
    
    func updateUIView(_ uiView: MKMapView, context: Context) {
        mapView.addOverlays(circles)
    }
    
    func makeCoordinator() -> Coordinator {
        return Coordinator(self)
    }
    
    class Coordinator: NSObject, MKMapViewDelegate, UIGestureRecognizerDelegate {
        @State var parent: MapTestQ2
        var tRecognizer = UITapGestureRecognizer()
        
        init(_ parent: MapTestQ2) {
            self.parent = parent
            super.init()
            self.tRecognizer = UITapGestureRecognizer(target: self, action: #selector(tapHandler))
            self.tRecognizer.delegate = self
            self.parent.mapView.addGestureRecognizer(tRecognizer)
        }
        
        func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
            guard let circleoverlay = overlay as? MKCircle else {return MKOverlayRenderer()}
            let circleRenderer = MKCircleRenderer(circle: circleoverlay)
            circleRenderer.strokeColor = .blue
            circleRenderer.fillColor = .systemCyan
            circleRenderer.alpha = 0.5
            return circleRenderer
          
        }
        
        @objc func tapHandler(_ gesture: UITapGestureRecognizer) {
            print("Tapped")
            let location = tRecognizer.location(in: self.parent.mapView)
            let coordinate = self.parent.mapView.convert(location, toCoordinateFrom: self.parent.mapView)
            let acircle = MKCircle(center: coordinate, radius: 500.0)
            self.parent.circles.append(acircle)
        }
    }
}

struct SEQ2: View {
    @State private var testcoord = CLLocationCoordinate2D(latitude: 37.33461, longitude: -122.00898)
    var body: some View {
                   MapTestQ2(centerCoordinate: $testcoord)
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.