2016-01-13 83 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

相关问题