定位处理与地图

一、定位处理

定位管理主要是通过GPS、蜂窝基站三角网、WiFi三种方式实现。

ios8系统下使用定位服务必须在info.plist中添加两条变量:

分别用于描述程序始终使用和使用期间使用定位的说明。对应手机设置中定位服务中的始终和使用应用程序期间两个选项。

1、在项目中引入框架CoreLoaction.framework。

2、创建一个定位服务管理类CLLocationManager来创建一个位置管理器,提供位置信息和高度信息,也可以监控进入和离开某个区域,还可以获得设备的运行方向。遵循代理

CLLocationManagerDelegate。

//定义坐标坐标
    var currLocation : CLLocation!
//创建位置管理器,用于定位服务管理类,它能够给我们提供位置信息和高度信息,也可以监控设备进入或离开某个区域,还可以获得设备的运行方向
    let locationManager : CLLocationManager = CLLocationManager()
//指定代理
        locationManager.delegate = self
        
        //精确到1000米,距离过滤器,定义了设备移动后获得位置信息的最小距离
        locationManager.distanceFilter = kCLLocationAccuracyBest
        
        //通过数字设置距离
//        locationManager.distanceFilter = 200
        
        //发出授权申请
        //NSLocationAlwaysUsageDescription 和 NSLocationWhenInUseUsageDescription 。至于在plist添加的方法,就是在plist中添加一个键值对,然后把请求允许对应的Key值复制粘贴进去就可以了。value值是什么都可以,这个值会在请求允许的对话框中显示出来给用户看。总之是你自己定的。
        locationManager.requestAlwaysAuthorization()
        
        //更新位置
        locationManager.startUpdatingLocation()
        
        //更新方向
        locationManager.startUpdatingHeading()
        
        print("定位开始")

通过didChangeAuthorizationStatus代理方法,可以获得设备是否允许使用定位服务。

//代理方法--判断是否可以使用定位服务
    func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus)
    {
        if status == CLAuthorizationStatus.NotDetermined || status == CLAuthorizationStatus.Denied
        {
            //允许使用定位服务
            //开始启动定位服务更新
            locationManager.startUpdatingLocation()
            //更新方向
            locationManager.startUpdatingHeading()
            print("定位开始")
        }
    }

定位改变时委托会执行这个方法,通过定义一个CLLocation坐标对象来接收坐标值。

//距离改变就会收到该委托方法,获取地理位置信息
    func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
    {
        //获取最新坐标
        currLocation = locations.last
        //获取经度
        longitudeTxt.text = "(currLocation.coordinate.longitude)"
        //获取纬度
        latitudeTxt.text = "(currLocation.coordinate.latitude)"
        //获取高度
        HeightTxt.text = "(currLocation.altitude)"
    }

两个坐标之间的距离可以通过func distanceFromLocation(other:Double) ->Double方法得到:

//计算两点之间距离
        let currentLocation = CLLocation(latitude: 53.204526, longitude: 50.111751)
        let targetLocation = CLLocation(latitude: 53.203715, longitude: 50.160374)
        let distance:CLLocationDistance  = currentLocation.distanceFromLocation(targetLocation);
        print("两点间距离是:(distance)")

通过方法:func locationManager(manager: CLLocationManager, didUpdateHeading newHeading: CLHeading)可以获取设备移动的方向,通过一组属性提供航向读数:

magneticHeading(磁场航向)和trueHeading(真实航向),如果航向为0.0,则前进方向为北;如果航向为90.0,则前进方向为东;如果航向为180.0,则前进方向为南;如果航向为270.0,则前进方向为西;只有打开定位服务才可以获得真实航向。

代码实现:

//获取方向
    func locationManager(manager: CLLocationManager, didUpdateHeading newHeading: CLHeading)
    {
        headingLabel.text = "(newHeading.trueHeading) degrees (true), (newHeading.magneticHeading)degrees (magnetic)"
        print( headingLabel.text)
    }

定位出现错误时会调用下面的委托方法:

func locationManager(manager: CLLocationManager, didFailWithError error: NSError)
    {
        print(error)
        if let clErr = CLError(rawValue: error.code){
            switch clErr {
            case .LocationUnknown:
                print("位置不明")
            case .Denied:
                print("允许检索位置被拒绝")
            case .Network:
                print("用于检索位置的网络不可用")
            default:
                print("未知的位置错误")
            }
        } else {
            print("其他错误")
            let alert = UIAlertView(title: "提示信息", message: "定位失败", delegate: nil, cancelButtonTitle: "确定")
            alert.show()
        }
    }

对于得到的定位信息我们需要把经纬度信息,反编码成一个地址,这里需要用到CLGeocoder类来实现地理反编码。

//地理信息反编码
    @IBAction func reverseGeocode(sender: AnyObject) {
        let geocoder = CLGeocoder()
        var p:CLPlacemark?
        geocoder.reverseGeocodeLocation(currLocation, completionHandler: { (placemarks, error) -> Void in
  
        // 强制 成 简体中文
        let array = NSArray(object: "zh-hans")
        NSUserDefaults.standardUserDefaults().setObject(array, forKey: "AppleLanguages")
        
        // 显示所有信息
        if error != nil {
                print("reverse geodcode fail: (error!.localizedDescription)")
                return
            }
            
            let pm = placemarks
            if (pm!.count > 0){
                p = placemarks![0]
                print(p)//输出反编码信息
                
                 print("country = (p?.country)")
                print("postalCode = (p?.postalCode)")
                print("location = (p?.location)")
                
            }else{
                print("No Placemarks!")
            }
        })
    }
//地理信息编码
    @IBAction func locationBianMa ()
    {
        //使用Google 服务进行地理编码
        let geocoder = CLGeocoder()
        var p:CLPlacemark?
        geocoder.geocodeAddressString("北京海淀区北三环西路39号", completionHandler: { (placemarks, error) -> Void in
            
            if error != nil {
                print("reverse geodcode fail: (error!.localizedDescription)")
                return
            }
            
            let pm = placemarks
            if (pm!.count > 0){
                p = placemarks![0]
                
                print("Longitude = (p?.location!.coordinate.longitude)")
                print("Latitude = (p?.location!.coordinate.latitude)")
                
                
                print(p)
            }else{
                print("No Placemarks!")
            }
            
        })
    }

二、地图

通过MapKit可以把地图嵌入到视图中,MapKit框架主要提供了四个功能:显示地图、CLLocation和地址之间的转换、支持在地图上做标记、把一个位置解析成地址。

首先导入MapKit.framework框架,通过代码或者静态创建MKMapView对象,可以显示地图。

// MARK: - Map
    @IBOutlet var mainMapView: MKMapView!
    @IBAction func showMap() {

        //使用代码创建地图
//        let mapView: MKMapView =  MKMapView(frame: CGRectMake(0, 0, 320, 200))
//        self.view.addSubview(mapView)
        
        //创建一个MKCoordinateSpan对象,设置地图的范围 越小越精确
        let latDelta = 0.05
        let longDelta = 0.05
        let currentLocationSpan: MKCoordinateSpan = MKCoordinateSpanMake(latDelta, longDelta)

        //定义一个区域,坐标使用定位获取的当前坐标locationManager.location.coordinate
        let currentRegion: MKCoordinateRegion = MKCoordinateRegionMake(locationManager.location!.coordinate, currentLocationSpan)
        
        //设置显示区域
        self.mainMapView.setRegion(currentRegion, animated: true)
        
        //设置地图显示类型,标准地图、卫星模式、混合模式。
        self.mainMapView.mapType = MKMapType.Standard //标准地图
        
        //设置代理
        self.mainMapView.delegate = self
        
        //创建一个大头针对象
        let objectAnnotation = MKPointAnnotation()
        
        //设置大头针显示位置,我们使用定位到的坐标
        objectAnnotation.coordinate = locationManager.location!.coordinate
        
        //设置点击大头针之后显示的标题
        objectAnnotation.title = "北京海淀"
        
        //设置点击大头针之后显示的描述
        objectAnnotation.subtitle = "北三环西路"
        
        //添加大头针
        self.mainMapView.addAnnotation(objectAnnotation)
    }

代理方法:

// MARK: - MKMapViewDelegate
    func mapView(mapView: MKMapView, regionWillChangeAnimated animated: Bool){
        //地图的缩放级别发生改变时,
    }
    
    func mapView(mapView: MKMapView, regionDidChangeAnimated animated: Bool){
        //地图的缩放完毕触发
    }
    
    func mapViewWillStartLoadingMap(mapView: MKMapView){
        //开始装载地图
    }
    
    func mapViewDidFinishLoadingMap(mapView: MKMapView){
        //结束装载地图
    }
    
    func mapViewDidFailLoadingMap(mapView: MKMapView, withError error: NSError){
        //装载失败
    }
    
    func mapViewWillStartRenderingMap(mapView: MKMapView){
        //开始渲染下载的地图块时调用
    }
    
    func mapViewDidFinishRenderingMap(mapView: MKMapView, fullyRendered: Bool){
        //渲染下载的地图结束时调用
    }
    
    
    //自定义大头针样式
    func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView?{
        if annotation is MKUserLocation {
            //return nil so map view draws "blue dot" for standard user location
            return nil
        }
        
        let reuseId = "pin"
        
        var pinView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId) as? MKPinAnnotationView
        
        if pinView == nil {
            
            //创建一个大头针视图
            pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
            
            pinView!.canShowCallout = true
            
            pinView!.animatesDrop = true
            
             //设置大头针颜色
            pinView!.pinColor = .Purple
            
            //设置大头针点注释视图的右侧按钮样式
            pinView!.rightCalloutAccessoryView = UIButton(type: UIButtonType.DetailDisclosure)
        }
        else {
            pinView!.annotation = annotation
        }
        return pinView
    }
    
    func mapView(mapView: MKMapView, didAddAnnotationViews views: [MKAnnotationView]){
        //添加注释视图
    }
    
    func mapView(mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl){
        
    }
    
    func mapView(mapView: MKMapView, didSelectAnnotationView view: MKAnnotationView){
        //点击大头针注释视图
    }
    
    func mapView(mapView: MKMapView, didDeselectAnnotationView view: MKAnnotationView){
        //取消点击大头针注释视图
    }
    
    func mapViewWillStartLocatingUser(mapView: MKMapView){
        //正在跟踪用户的位置
    }
    
    func mapViewDidStopLocatingUser(mapView: MKMapView){
        //停止跟踪用户的位置
    }
    
    func mapView(mapView: MKMapView, didUpdateUserLocation userLocation: MKUserLocation){
        //更新用户的位置
    }
    
    func mapView(mapView: MKMapView, didFailToLocateUserWithError error: NSError){
        //跟踪用户的位置 失败
    }
    
    func mapView(mapView: MKMapView, annotationView view: MKAnnotationView, didChangeDragState newState: MKAnnotationViewDragState, fromOldState oldState: MKAnnotationViewDragState){
        //移动annotation位置时调用。newState为宏,表示几个状态。是否能移动位置在annotation中设置。
    }
    
    func mapView(mapView: MKMapView, didChangeUserTrackingMode mode: MKUserTrackingMode, animated: Bool){
     
        //改变UserTrackingMode
    }
    
    func mapView(mapView: MKMapView, rendererForOverlay overlay: MKOverlay) -> MKOverlayRenderer{
        //设置overlay的渲染
        return MKOverlayRenderer()
    }
    
    func mapView(mapView: MKMapView, didAddOverlayRenderers renderers: [MKOverlayRenderer])
    {
        //地图上加上了overlayRenderers后调用
    }
原文地址:https://www.cnblogs.com/fengmin/p/5718414.html