簡體   English   中英

如何檢測 mapView 在 Swift 中移動並更新縮放

[英]How to detect the mapView was moved in Swift and update zoom

我正在嘗試在 Swift 2 中為我的 map 設置最小縮放級別。我找不到任何關於如何限制 map 被放大太多的文檔。我決定嘗試監視 map 運動(例如拖動或縮放)然后將MKZoomScale設置回最小值。

我為regionDidChangeAnimated找到的大部分答案都在 Objective C 中,我不知道,我在將它們轉換為 Swift 時遇到了麻煩。

我嘗試實現@hEADcRASH 的答案: https://stackoverflow.com/a/30924768/4106552 ,但當 map 在模擬器中移動時,它不會觸發並向控制台打印任何內容。

誰能告訴我我做錯了什么? 我是 Swift 的新手,所以這可能是一個小錯誤。 另外,讓我知道是否有一種輕量級的方法可以解決限制 map 上的縮放級別的問題。我擔心移動監視器會稍微減慢 map animation 的速度。 謝謝您的幫助。

這是我的觀點 controller.import UIKit import Parse import MapKit

class SearchRadiusViewController: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate {

@IBOutlet weak var map: MKMapView!

@IBOutlet weak var menuBtn: UIBarButtonItem!

var locationManager = CLLocationManager()

override func viewDidLoad() {
    super.viewDidLoad()

    //menu button control
    if self.revealViewController() != nil {
        menuBtn.target = self.revealViewController()
        menuBtn.action = "revealToggle:"
        self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
    }

    //user location
    locationManager.delegate = self
    locationManager.desiredAccuracy = kCLLocationAccuracyBest
    locationManager.requestWhenInUseAuthorization()
    locationManager.startUpdatingLocation()


}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}


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

    //set map
    let location:CLLocationCoordinate2D = manager.location!.coordinate
    let latitude = location.latitude
    let longitude = location.longitude
    let latDelta:CLLocationDegrees = 0.1
    let longDelta:CLLocationDegrees = 0.1
    let span:MKCoordinateSpan = MKCoordinateSpanMake(latDelta, longDelta)
    let maplocation:CLLocationCoordinate2D = CLLocationCoordinate2DMake(latitude, longitude)
    let region:MKCoordinateRegion = MKCoordinateRegionMake(maplocation, span)
    map.setRegion(region, animated: true)

    //stop updating location, only need user location once to position map.
    manager.stopUpdatingLocation()

}

//Attempt to monitor for map movement based on hEADcRASH's answer.
private var mapChangedFromUserInteraction = false

private func mapViewRegionDidChangeFromUserInteraction() -> Bool {
    let view = self.map.subviews[0]
    //  Look through gesture recognizers to determine whether this region change is from user interaction
    if let gestureRecognizers = view.gestureRecognizers {
        for recognizer in gestureRecognizers {
            if( recognizer.state == UIGestureRecognizerState.Began || recognizer.state == UIGestureRecognizerState.Ended ) {
                return true
            }
        }
    }
    return false
}

func mapView(mapView: MKMapView, regionWillChangeAnimated animated: Bool) {
    print("yes")
    mapChangedFromUserInteraction = mapViewRegionDidChangeFromUserInteraction()
    if (mapChangedFromUserInteraction) {
        // user changed map region
        print("user changed map in WILL")
    }
}

func mapView(mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
            print("yes ddd")
    if (mapChangedFromUserInteraction) {
        // user changed map region
        print("user changed map in Did")
    }
}
}

在回顧並結合了許多其他問題/答案以及@lorenzoliveto的幫助后,我開始在Swift中使用它。 如果有更好/更輕巧的方法來實現相同目的,請發表評論。

我將self.map.delegate = self添加到viewDidLoad函數。

下面是有關我如何監視地圖移動的代碼,然后,一旦用戶將“地圖”放大到“太遠”並且地圖的寬度低於2英里,我便使用mapView.setRegion縮小地圖。

private var mapChangedFromUserInteraction = false

private func mapViewRegionDidChangeFromUserInteraction() -> Bool {
    let view = self.map.subviews[0]
    //  Look through gesture recognizers to determine whether this region change is from user interaction
    if let gestureRecognizers = view.gestureRecognizers {
        for recognizer in gestureRecognizers {
            if( recognizer.state == UIGestureRecognizerState.Began || recognizer.state == UIGestureRecognizerState.Ended ) {
                return true
            }
        }
    }
    return false
}

func mapView(mapView: MKMapView, regionWillChangeAnimated animated: Bool) {
    mapChangedFromUserInteraction = mapViewRegionDidChangeFromUserInteraction()
    if (mapChangedFromUserInteraction) {
        // user will change map region
        print("user WILL change map.")

        // calculate the width of the map in miles.
        let mRect: MKMapRect = mapView.visibleMapRect
        let eastMapPoint = MKMapPointMake(MKMapRectGetMinX(mRect), MKMapRectGetMidY(mRect))
        let westMapPoint = MKMapPointMake(MKMapRectGetMaxX(mRect), MKMapRectGetMidY(mRect))
        let currentDistWideInMeters = MKMetersBetweenMapPoints(eastMapPoint, westMapPoint)
        let milesWide = currentDistWideInMeters / 1609.34  // number of meters in a mile
        print(milesWide)
        print("^miles wide")

        // check if user zoomed in too far and zoom them out.
        if milesWide < 2.0 {
            var region:MKCoordinateRegion = mapView.region
            var span:MKCoordinateSpan = mapView.region.span
            span.latitudeDelta = 0.04
            span.longitudeDelta = 0.04
            region.span = span;
            mapView.setRegion(region, animated: true)
            print("map zoomed back out")
        }

    }
}

func mapView(mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
    if (mapChangedFromUserInteraction) {
        // user changed map region
        print("user CHANGED map.")
        print(mapView.region.span.latitudeDelta)
        print(mapView.region.span.longitudeDelta)

        // calculate the width of the map in miles.
        let mRect: MKMapRect = mapView.visibleMapRect
        let eastMapPoint = MKMapPointMake(MKMapRectGetMinX(mRect), MKMapRectGetMidY(mRect))
        let westMapPoint = MKMapPointMake(MKMapRectGetMaxX(mRect), MKMapRectGetMidY(mRect))
        let currentDistWideInMeters = MKMetersBetweenMapPoints(eastMapPoint, westMapPoint)
        let milesWide = currentDistWideInMeters / 1609.34  // number of meters in a mile
        print(milesWide)
        print("^miles wide")

        // check if user zoomed in too far and zoom them out.
        if milesWide < 2.0 {
            var region:MKCoordinateRegion = mapView.region
            var span:MKCoordinateSpan = mapView.region.span
            span.latitudeDelta = 0.04
            span.longitudeDelta = 0.04
            region.span = span;
            mapView.setRegion(region, animated: true)
            print("map zoomed back out")
        }
    }

更新:3/7,我在上面的實現中發現了一個有趣的錯誤。 在模擬器上,單擊以放大時效果很好,但是當您使用雙指進行縮放(選項+單擊)時,模擬器將停止,允許您在將縮放動畫化后再拖動地圖。 這也發生在我iPhone的Beta版上。 我在將地圖動畫化回其位置的塊周圍添加了dispatch_async ,它似乎正在模擬器上運行。 設置動畫后,它不再顯示為凍結狀態,我可以繼續在地圖上拖動並嘗試放大。

dispatch_async(dispatch_get_main_queue(), {
   var region:MKCoordinateRegion = mapView.region
   var span:MKCoordinateSpan = mapView.region.span
   span.latitudeDelta = 0.04
   span.longitudeDelta = 0.04
   region.span = span;
   mapView.setRegion(region, animated: true)
   print("map zoomed back out")
})

對我有用的解決方案是我設置縮放范圍的解決方案。 在提出問題時,此方法可能不可用。 下面的代碼片段是我使用的。 我不完全確定距離單位是什么,但我相信它們是米。 弄清楚在給定實例中什么范圍有效可能是一個反復試驗的問題。

        let mapView = MKMapView(frame: .zero)        
        let zoomRange = MKMapView.CameraZoomRange(
            minCenterCoordinateDistance: 120000,
            maxCenterCoordinateDistance: 1600000
        )
        mapView.cameraZoomRange = zoomRange

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM