2016-01-13 108 views
2

我試圖在Swift 2中設置我的地圖上的最小縮放級別。我找不到任何有關如何限制地圖放大得太遠的文檔我決定嘗試的是監視地圖移動(例如拖動或縮放),然後將MKZoomScale設置回最小值。如何檢測mapView在Swift中移動並更新縮放

我發現的regionDidChangeAnimated的大部分答案都在Objective C中,我不知道,但我很難將它們轉換爲Swift。

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

誰能告訴我我做錯了什麼?我是Swift新手,所以這可能是一個小錯誤。此外,讓我知道是否有一個輕量級的方法來解決限制地圖上的縮放級別。我擔心移動顯示器會讓地圖動畫變慢一點。謝謝您的幫助。

這是我的視圖控制器。 進口的UIKit 進口解析 進口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") 
    } 
} 
} 
+0

您是否在故事板中設置mapView的委託?如果不是的話,你應該在viewDidLoad方法中添加self.map.delegate = self。 – lorenzoliveto

+0

感謝@lorenzoliveto,將'self.map.delegate = self'添加到viewDidLoad正在工作。 mapViewRegionDidChangeAnimated正在工作!您是否有意見設置最大縮放級別的最佳方式?我應該走觀看地圖移動/縮放和重置地圖縮放的路線嗎? – tylerSF

+0

是的,我認爲這是您擁有的唯一選擇。 regionWillChangeAnimated:在滾動過程中多次調用,而regionDidChangeAnimated:在滾動後僅調用一次。嘗試在兩者中添加重置代碼並查看性能如何受到影響。 – lorenzoliveto

回答

3

審查,並結合了一些其他問題/答案和@lorenzoliveto我知道了在斯威夫特工作後幫。如果有更好的/更輕量級的方式來實現相同的事情,請留下評論。

我將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,我在上面的實現中發現了一個有趣的bug。在模擬器上,它可以在單擊縮放時正常工作,但是當您使用縮放來縮放(選項+單擊)時,模擬器會停止,讓您在縮放動畫後拖動地圖。這也發生在我的iPhone上的測試版本。我添加了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") 
}) 
+2

我一直在尋找如何檢測地圖改變,並發現這一點。似乎我只需要'func mapViewRegionDidChangeFromUserInteraction()'感謝分享! – John

相關問題