美文网首页iOS程序员iOS Developer
你真的弄清楚 IOS 中的地理位置的获取了吗?

你真的弄清楚 IOS 中的地理位置的获取了吗?

作者: 修行猿 | 来源:发表于2016-08-08 22:22 被阅读3181次

    1.在前台的时候获取地理位置信息

    ios 8/9

    • 在info.plist中配置NSLocationWhenInUseUsageDescription的值,否则上面的方法无效

    • 调用.requestWhenInUseAuthorization()获取前台获取地理位置权限

    • 调用.startUpdatingLocation()

    代码示例

    class ViewController: UIViewController {
        lazy var locateM : CLLocationManager = {
           let locate  = CLLocationManager()
            locate.delegate = self
            locate.requestWhenInUseAuthorization()
            return locate
        }()
        override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
            self.locateM.startUpdatingLocation()
        }
    }
    extension ViewController : CLLocationManagerDelegate{
        func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
            print("位置信息已经更新")
        }
    }
    

    2.前后台获取,但是后台获取的时候,屏幕上方有蓝框提示用户正在后台获取

    ios8

    • 调用.requestWhenInUseAuthorization()获取前台获取地理位置权限
    • 在info.plist中配置NSLocationWhenInUseUsageDescription的值,否则上面的方法无效
    • 设置Capabilities>BackgroundModes>Location Updates 打对勾
    • 调用.startUpdatingLocation()

    ios9

    • 调用.requestWhenInUseAuthorization()获取前台获取地理位置权限
    • 设置 .allowsBackgroundLocationUpdates = true (ios 9需要执行)
    • 在info.plist中配置NSLocationWhenInUseUsageDescription的值,否则上面的方法无效
    • 设置Capabilities>BackgroundModes>Location Updates 打对勾 (如果第二步做了,此步没做,直接crash)
    • 调用.startUpdatingLocation()

    ios8/ios9可以后台蓝框定位的代码示例:

    class ViewController: UIViewController {
        lazy var locateM : CLLocationManager = {
           let locate  = CLLocationManager()
            locate.delegate = self
            locate.requestWhenInUseAuthorization()
            if #available(iOS 9.0, *) {
                locate.allowsBackgroundLocationUpdates = true
            }
            return locate
        }()
        override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        
            
            self.locateM.startUpdatingLocation()
        }
    }
    extension ViewController : CLLocationManagerDelegate{
        func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
            print("位置信息已经更新")
        }
    }
    

    3.后台获取,后台获取的时候,屏幕上方无蓝框提示

    • 调用.requestAlwaysAuthorization()获取前台获取地理位置权限
    • 在info.plist中配置NSLocationAlwaysUsageDescription的值,否则上面的方法无效
    • 设置 .allowsBackgroundLocationUpdates = true (ios 9需要执行)
    • 设置Capabilities>BackgroundModes>Location Updates 打对勾 (本步骤在ios 8中可以不做设置,但是在ios9中如果第三步做了,而此步没有做,直接crash)
    • 调用.startUpdatingLocation()

    代码示例

    class ViewController: UIViewController {
        lazy var locateM : CLLocationManager = {
           let locate  = CLLocationManager()
            locate.delegate = self
            locate.requestAlwaysAuthorization()
            if #available(iOS 9.0, *) {
                locate.allowsBackgroundLocationUpdates = true
            }
            return locate
        }()
        override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        
            
            self.locateM.startUpdatingLocation()
        }
    }
    extension ViewController : CLLocationManagerDelegate{
        func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
            print("位置信息已经更新")
        }
    }
    

    4.权限改变的通知

    注意:在Denied或者NotDetermined的状态下startUpdatingLocation,开始监听之后,当状态改变成允许的状态时,会直接进入监听状态,不必再次调用startUpdateingLocation

    func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
            switch status {
            case .AuthorizedAlways:
                print("始终")
            case .AuthorizedWhenInUse:
                print("使用的时候")
            case .Denied:
                print("拒绝")
                if CLLocationManager.locationServicesEnabled() {
                    print("真拒绝了")
                }else{
                    print("是关闭了定位服务")
                }
            case .NotDetermined:
                print("第一次,尚未决定")
            case .Restricted:
                print("没有权限的")
    
            }
        }
    

    5.过滤距离

    很多时候我们需要监听函数只调用一次来获取用户当前的位置

    • 在监听函数中停止监听
    • 设置监听的过滤距离
      //如果监听器已经开启,此值修改之后立即生效
      self.locateM.distanceFilter = 100 //每100米,调用一次监听
    

    6.精度

    注意:越精确越耗电,定位的时间越长,如果要定位城市,没有必要选最精确的

      self.locateM.desiredAccuracy = kCLLocationAccuracyBest
     //kCLLocationAccuracyBestForNavigation
     //kCLLocationAccuracyBest
     //kCLLocationAccuracyNearestTenMeters
     //kCLLocationAccuracyHundredMeters
     //kCLLocationAccuracyKilometer
     //kCLLocationAccuracyThreeKilometers
    

    7.CLLocation详解

    
    public var coordinate: CLLocationCoordinate2D { get }     //经纬度
    public var altitude: CLLocationDistance { get }           //海拔
    public var horizontalAccuracy: CLLocationAccuracy { get } //位置信息是否有效,如果为负数,则无效  
    public var verticalAccuracy: CLLocationAccuracy { get }   //海拔数据是否有效,如果为负数,则无效  
    public var course: CLLocationDirection { get }            //当前的角度(0-359.9)
    public var speed: CLLocationSpeed { get }                 //当前的速度     
    public var timestamp: NSDate { get }                      //位置确定的时间戳       
    public var floor: CLFloor? { get }                        //楼层(前提是已经注册的建筑),如果没有为nil      
    
    //计算两个经纬度之间的距离       
    public func distanceFromLocation(location: CLLocation) -> CLLocationDistance
    

    8.指南针小例子

    class ViewController: UIViewController {
        
        @IBOutlet weak var mImageView: UIImageView!
        lazy var locateM : CLLocationManager = {
           let locate  = CLLocationManager()
            locate.delegate = self
            locate.requestAlwaysAuthorization()
            if #available(iOS 9.0, *) {
                locate.allowsBackgroundLocationUpdates = true
            }
            return locate
        }()
        override func viewDidLoad() {
            super.viewDidLoad()
            if(CLLocationManager.headingAvailable()){
                self.locateM.startUpdatingHeading()
            }else{
                print("当前磁力计有问题")
            }   
        }
    }
    extension ViewController : CLLocationManagerDelegate{
        func locationManager(manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) {
            //1.拿到当前设备对正朝向的角度
            let angle = newHeading.magneticHeading
            //2.把角度转换成弧度
            let hudu = CGFloat(angle / 180 * M_PI)
            //3.反向旋转照片
            UIView.animateWithDuration(0.5) { 
                self.mImageView.transform = CGAffineTransformMakeRotation(-hudu)
            }
        }
    }
    

    9.区域的监听

    class ViewController: UIViewController {
        lazy var locateM : CLLocationManager = {
           let locate  = CLLocationManager()
            locate.delegate = self
            locate.requestAlwaysAuthorization()
            if #available(iOS 9.0, *) {
                locate.allowsBackgroundLocationUpdates = true
            }
            return locate
        }()
        override func viewDidLoad() {
            super.viewDidLoad()
            //首先应该判断当前是否可以监听某个区域
            if CLLocationManager.isMonitoringAvailableForClass(CLCircularRegion){
                //1.创建区域
                let center = CLLocationCoordinate2DMake(21.123, 121.345)
                var  distance : CLLocationDistance = 1000
                //限制监听的范围不能超过最大的范围
                if distance < locateM.maximumRegionMonitoringDistance{
                    distance = locateM.maximumRegionMonitoringDistance
                }
                let region = CLCircularRegion(center: center, radius: distance, identifier: "xiaoxiao")
                //2.监听区域
                self.locateM.startMonitoringForRegion(region)
                //3.判断当前状态是否是在区域内还是区域外,
                //在`didDetermineState`代理方法中获得结果
                self.locateM.requestStateForRegion(region)
            }
        }
    }
    extension ViewController : CLLocationManagerDelegate{
        func locationManager(manager: CLLocationManager, didEnterRegion region: CLRegion) {
            print("进入了区域"+region.identifier)
        }
        func locationManager(manager: CLLocationManager, didExitRegion region: CLRegion) {
            print("出了区域"+region.identifier)
        }
        func locationManager(manager: CLLocationManager, didDetermineState state: CLRegionState, forRegion region: CLRegion) {
            //获取刚开始是否在区域内或者区域外
            if region.identifier == "xiaoxiao"{
                switch state {
                case .Inside:
                    print("已经是区域内的")
                case .Outside:
                    print("没有在区域内")
                case .Unknown:
                    print("不清楚")
                }
            }
        }
    }
    

    10.地理编码与反地理编码

    • 地理编码
    let geoCoder = CLGeocoder()
    geoCoder.geocodeAddressString("广州") { (pls:[CLPlacemark]?, error : NSError?) in
         if error == nil{
            print("地址编码成功")
            print(pls?.last?.location)
         }else{
            print("错误 \(error)")
         }       
    }
    

    打印

    地址编码成功
    Optional(<+23.12517800,+113.28063700> +/- 100.00m (speed -1.00 mps / course -1.00) @ 8/14/16, 9:49:22 PM China Standard Time)
    
    • 反地理编码
    let geoCoder = CLGeocoder()
    geoCoder.reverseGeocodeLocation(CLLocation(latitude:23.125,longitude: 113.280)) { (pls:[CLPlacemark]?, error:NSError?) in
                if error == nil{
                    print("地址反编码成功 城市:\(pls?.last?.locality)")
                    print(pls?.last?.addressDictionary)
                }else{
                    print("错误 \(error)")
                }
            }
    

    打印

    地址反编码成功 城市:Optional("Guangzhou")
    Optional([SubLocality: Yuexiu, Street: Yunhai Tongjin No.11, State: Guangdong, CountryCode: CN, Thoroughfare: Yunhai Tongjin No.11, Name: Luo Sangmeidi, Country: China, FormattedAddressLines: <__NSArrayM 0x7ff1da5652d0>(
    Yunhai Tongjin No.11 Yuexiu,
    Guangzhou,
    Guangdong China
    )
    , City: Guangzhou])
    
    • 注意同一个CLGeocoder对象,不能同时编码与反编码
      比如
            let geoCoder = CLGeocoder()
            geoCoder.geocodeAddressString("广州") { (pls:[CLPlacemark]?, error : NSError?) in
                ...
                
            }
            geoCoder.reverseGeocodeLocation(CLLocation(latitude:23.125,longitude: 113.280)) { (pls:[CLPlacemark]?, error:NSError?) in
                ...
            }
    

    这样只会打印第一个编码成功的结果

    11.CLPlacemark对象详解

    
    @NSCopying public var location: CLLocation? { get }              //经纬度
    @NSCopying public var region: CLRegion? { get }                  //所关联的地理区域
    @available(iOS 9.0, *)
    @NSCopying public var timeZone: NSTimeZone? { get }              //时间域
    public var addressDictionary: [NSObject : AnyObject]? { get }    //详细地址信息
    
    //addressDictionary中的属性
    public var name: String? { get }                   //名字 
    public var thoroughfare: String? { get }           //街道名字
    public var subThoroughfare: String? { get }        //子街道名字
    public var locality: String? { get }               //城市名称
    public var subLocality: String? { get }            //邻城市名称
    public var administrativeArea: String? { get }     //行政区域 比如:CA
    public var subAdministrativeArea: String? { get }  //子行政区域
    public var postalCode: String? { get }             //邮政编码
    public var ISOcountryCode: String? { get }         //国家代码表
    public var country: String? { get }                //国家
    public var inlandWater: String? { get }            //内陆水域
    public var ocean: String? { get }                  //海洋
    public var areasOfInterest: [String]? { get }      //兴趣点
    

    以上均为看小码哥视频所总结

    相关文章

      网友评论

      • JopiNFlyyy:请问startUpdatingLocation能设置时间间隔吗
      • _comeSoon:看来小码哥没告诉你,这才是“iOS”的正确写法,调整一下吧?
        修行猿:@直持小崔 有道理
        直持小崔:@六道真君 乔爷死不瞑目 打死你
        修行猿:@_comeSoon 我知道,但是并不喜欢这样的写法。太丑,还不习惯。

      本文标题:你真的弄清楚 IOS 中的地理位置的获取了吗?

      本文链接:https://www.haomeiwen.com/subject/ovvrsttx.html