MapKit 缩放到用户当前位置

Posted

技术标签:

【中文标题】MapKit 缩放到用户当前位置【英文标题】:MapKit zoom to user current location 【发布时间】:2017-05-02 12:44:18 【问题描述】:

我试图简单地在地图上显示用户的位置,但我需要在应用程序启动时,地图应该缩放到当前位置,但我不知道为什么地图根本不缩放,就像这样:

代码如下:

class MapViewController: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate 

    @IBOutlet weak var mapView: MKMapView!
    var locationManager = CLLocationManager()

    override func viewDidLoad() 
        super.viewDidLoad()

        mapView.delegate = self
        mapView.showsUserLocation = true
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.requestWhenInUseAuthorization()
        locationManager.delegate = self
        DispatchQueue.main.async 
            self.locationManager.startUpdatingLocation()
        
    

    func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) 
        let location = locations.last as! CLLocation
        let center = CLLocationCoordinate2D(latitude: location.coordinate.latitude, longitude: location.coordinate.longitude)
        var region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1))
        region.center = mapView.userLocation.coordinate
        mapView.setRegion(region, animated: true)
    

【问题讨论】:

删除region.center = mapView.userLocation.coordinate @shallowThought 我做了,但没有任何改变 【参考方案1】:

我遇到了类似的问题,浪费了 4 天时间思考出了什么问题。最后通过在viewDidLoad 方法中创建这些代码行来解决:

    //Zoom to user location
    let noLocation = CLLocationCoordinate2D()
    let viewRegion = MKCoordinateRegionMakeWithDistance(noLocation, 200, 200)
    mapView.setRegion(viewRegion, animated: false)
    mapView.showsUserLocation = true

ViewDidLoad 方法中添加这些新的更改代码:

override func viewDidLoad() 

    super.viewDidLoad()

    let locationManager = CLLocationManager()
    locationManager.delegate = self
    locationManager.desiredAccuracy = kCLLocationAccuracyBest

    // Check for Location Services
    if (CLLocationManager.locationServicesEnabled()) 
        locationManager.requestAlwaysAuthorization()
        locationManager.requestWhenInUseAuthorization()
    

    //Zoom to user location
    if let userLocation = locationManager.location?.coordinate 
        let viewRegion = MKCoordinateRegionMakeWithDistance(userLocation, 200, 200)
        mapView.setRegion(viewRegion, animated: false)
    

    self.locationManager = locationManager

    DispatchQueue.main.async 
        self.locationManager.startUpdatingLocation()
    


希望这有助于解决您的问题。如果有任何进一步的问题,请随时发表评论。谢谢

【讨论】:

此代码 sn-p 失败,因为 locationManager 在第一次调用时未初始化。远程线路:locationManager.desiredAccuracy = kCLLocationAccuracyBest locationManager.delegate = self 为什么locationManager.requestWhenInUseAuthorization() 行重复? 如果你再读一遍它会有两个不同的想法:requestWhenInUseAuthorization 和 requestAlwaysAuthorization 为了放大用户位置,需要在上面的代码中进行更改。 -> 让 noLocation = locationManager.location?.coordinate @ViruMax 我觉得为时已晚,但您需要添加mapView.showsUserLocation = true 才能看到蓝色圆圈。【参考方案2】:

这是 Swift 3,XCode 8.2 的另一种方法。首先,写出一个辅助函数:

let homeLocation = CLLocation(latitude: 37.6213, longitude: -122.3790)
let regionRadius: CLLocationDistance = 200
func centerMapOnLocation(location: CLLocation)

    let coordinateRegion = MKCoordinateRegionMakeWithDistance(location.coordinate,
                                           regionRadius * 2.0, regionRadius * 2.0)
    mapView.setRegion(coordinateRegion, animated: true)

然后,拨打viewDidLoad()

mapView.showsUserLocation = true
centerMapOnLocation(location: homeLocation)

这将使用放大的变量中指定的位置启动应用程序。

【讨论】:

如果homeLocation能被代码自动找到会更有帮助。【参考方案3】:

在 Swift 4.2 中,此代码发生了变化。下面是它现在的工作方式:

import UIKit
import MapKit
import CoreLocation

class MapVC: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate 

    @IBOutlet weak var mapView: MKMapView!
    var locationManager = CLLocationManager()
    let authorizationStatus = CLLocationManager.authorizationStatus()
    let regionRadius: Double = 1000

    override func viewDidLoad() 
        super.viewDidLoad()
        mapView.delegate = self
        locationManager.delegate = self
        configureLocationServices()
    

    func centerMapOnUserLocation() 
        guard let coordinate = locationManager.location?.coordinate else return
        let coordinateRegion = MKCoordinateRegion(center: coordinate, latitudinalMeters: regionRadius, longitudinalMeters: regionRadius)
        mapView.setRegion(coordinateRegion, animated: true)
    

    func configureLocationServices() 
        if authorizationStatus == .notDetermined 
            locationManager.requestAlwaysAuthorization()
         else 
            return
        
    

    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) 
        centerMapOnUserLocation()
    


【讨论】:

您可能希望使用CLLocationDistance 类型来代替regionRadius【参考方案4】:

代码:

import UIKit
import MapKit

class ViewController: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate 

@IBOutlet weak var mapview: MKMapView!

let locationmanager = CLLocationManager()

override func viewDidLoad() 
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    mapview.mapType = MKMapType.standard

    let location = CLLocationCoordinate2DMake(22.4651, 70.0771)

    let span = MKCoordinateSpanMake(0.5, 0.5)
    let region =  MKCoordinateRegionMake(location, span)
    mapview.setRegion(region, animated: true)

    let annonation = MKPointAnnotation()
    annonation.coordinate = location
    annonation.title = "Chandi Bazar"
    annonation.subtitle = "Jamnagar"
    //
    mapview.addAnnotation(annonation)

    self.locationmanager.requestWhenInUseAuthorization()

    if CLLocationManager.locationServicesEnabled()
    
        locationmanager.delegate = self
        locationmanager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
        locationmanager.startUpdatingLocation()
    


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

    let locValue:CLLocationCoordinate2D = manager.location!.coordinate
    print("locations = \(locValue.latitude) \(locValue.longitude)")

    locationmanager.stopUpdatingLocation()


func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView?

    if (annotation is MKUserLocation)
    
        return nil
    

    let annotationidentifier = "Annotationidentifier"

    var annotationview:MKAnnotationView
    annotationview = MKAnnotationView(annotation: annotation, reuseIdentifier: annotationidentifier)

    let btn = UIButton(type: .detailDisclosure)

    btn.addTarget(self, action: #selector(ViewController.hirenagravat(sender:)), for: .touchUpInside)

    annotationview.rightCalloutAccessoryView = btn

    annotationview.image = UIImage(named: "images (4).jpeg")

    annotationview.canShowCallout = true

    return annotationview


func hirenagravat(sender:UIButton)

    let fvc = storyboard?.instantiateViewController(withIdentifier: "secondViewController") as? secondViewController
    self.navigationController?.pushViewController(fvc!, animated: true)

【讨论】:

【参考方案5】:

当您设置区域时 -> 您无法再缩放地图。下面来解决这个问题

func yourFuncName() 
//this is global var
regionHasBeenCentered = false
if !self.regionHasBeenCentered 
    let span: MKCoordinateSpan = MKCoordinateSpanMake(0.01, 0.01)
    let userLocation: CLLocationCoordinate2D = CLLocationCoordinate2DMake(_cllocationOfUserCurrentLocation!.coordinate.latitude, _cllocationOfUserCurrentLocation!.coordinate.longitude)
    let region: MKCoordinateRegion = MKCoordinateRegionMake(userLocation, span)

    self.mapView.setRegion(region, animated: true)
    self.regionHasBeenCentered = true
    

    self.mapView.showsUserLocation = true

【讨论】:

【参考方案6】:

尝试使用 MKMapViewDelegate 函数:

var isInitiallyZoomedToUserLocation: Bool = false 

func mapView(_ mapView: MKMapView, didUpdate userLocation: MKUserLocation) 
    if !isInitiallyZoomedToUserLocation 
       isInitiallyZoomedToUserLocation = true
       mapView.showAnnotations([userLocation], animated: true)
    

【讨论】:

同意这个,已经有位置权限的就不用加CLLocationManager了 我们可以使用 setRegion 来代替 showAnnotations(),因为我们现在可以访问 userLocation。让 viewRegion = MKCoordinateRegion(center: userLocation.coordinate, latitudinalMeters: 200, verticalMeters: 200) mapView.setRegion(viewRegion, animated: true)【参考方案7】:

swift 4.1 中。要更改缩放级别,您需要更改跨度值,即 MKCoordinateSpan(latitudeDelta: 0.95, longitudeDelta: 0.95)

 let lat =  "33.847105"
    let long = "-118.2673272"
    let region = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: Double(lat)!, longitude: Double(long)!), span: MKCoordinateSpan(latitudeDelta: 0.95, longitudeDelta: 0.95))
    DispatchQueue.main.async 
        self.mapView.setRegion(region, animated: true)
    

Swift 5.0

let span = MKCoordinateSpan.init(latitudeDelta: 0.01, longitudeDelta:
0.01)
let coordinate = CLLocationCoordinate2D.init(latitude: 21.282778, longitude: -157.829444) // provide you lat and long 
let region = MKCoordinateRegion.init(center: coordinate, span: span)
mapView.setRegion(region, animated: true)

【讨论】:

【参考方案8】:
func animateToUserLocation() 
    if let annoation = mapView.annotations.filter ( $0 is MKUserLocation ).first 
        let coordinate = annoation.coordinate
        let viewRegion = MKCoordinateRegion(center: coordinate, latitudinalMeters: 200, longitudinalMeters: 200)
        mapView.setRegion(viewRegion, animated: true)
    

【讨论】:

以上是关于MapKit 缩放到用户当前位置的主要内容,如果未能解决你的问题,请参考以下文章

转到/缩放到当前位置功能(MapKit)

iPhone Mapkit 蓝点/用户位置区域缩放问题

iOS mapKit在用户当前位置更新时刷新方向

ios:mapkit如何在地图上启用当前位置按钮?

使用 SwiftUI 和 MapKit 检索用户当前位置

为啥我的 MapKit 中的蓝点(用户位置)会移动?