美文网首页
Swift 简易定位Demo(基于CLLocationManag

Swift 简易定位Demo(基于CLLocationManag

作者: YYYYYY25 | 来源:发表于2019-03-08 16:39 被阅读0次

    这是一个简易的一次性定位工具的封装,基于系统CLLocationManager。如果项目中需要获取只是简单的获取定位信息,可以在这个demo的基础上进行扩展。

    准备:

    创建demo项目,并通过Storyboard添加如下图所示的两个button事件。
    1 获取定位
    2 判断定位功能是否可用


    视图结构
    创建定位单例:
    import CoreLocation
    
    class LocationManager: NSObject {
        static let sharedInstance = LocationManager()
        private override init() {}
    }
    

    声明一个用于管理定位操作的工具类,单例处理,并导入 Conre Location 框架。

    初始化操作:
    private let locationMgr = CLLocationManager() // 1
    
    func config() {
        guard isLocationServiceEnabled() else { // 2
            return
        }
        
        let status  = CLLocationManager.authorizationStatus()
    
        // 用户没有决定是否使用定位服务
        if status == .notDetermined {
            locationMgr.requestWhenInUseAuthorization()
            return
        }
        
        locationMgr.delegate = self // 3
        locationMgr.desiredAccuracy = kCLLocationAccuracyBest
        locationMgr.distanceFilter = 1000.0
        locationMgr.startUpdatingLocation()
    }
    

    1 创建CLLocationManager对象,并用私有属性管理。(这里不能把CLLocationManager声明为config方法中的局部变量,因为超出作用域后,系统获取定位权限的弹窗会自动消失)
    2 声明isLocationServiceEnabled方法,判断系统是否开通定位权限。

    private func isLocationServiceEnabled() -> Bool {
        if CLLocationManager.locationServicesEnabled() {
            return true
        } else {
            return false
        }
    }
    

    3 实现CLLocationManagerDelegate协议

    var city: String = "Undefault" 
    
    extension LocationManager : CLLocationManagerDelegate {
    
        func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
            locationMgr.stopUpdatingLocation()
            let currentLocation = locations.last
            let geoCoder = CLGeocoder()
            
            // let userdefault = UserDefaults.standard
            // let userDefaultLanguages = userdefault.object(forKey: "AppleLanguages")
            // userdefault.set(NSArray(objects: "zh-Hans-CN"), forKey: "AppleLanguages")
    
            geoCoder.reverseGeocodeLocation(currentLocation!) { (placemarks, error) in
                
                if (error != nil) {print("reverse geodcode fail:" +  "\(error?.localizedDescription ?? "")")}
                
                let placeMark = placemarks?.last
        
                if let cty = placeMark?.locality {
                    self.city = cty
                }else {
                    self.city = placeMark?.administrativeArea ?? "Undefault"
                }
                
                print(self.city)
                
            }
            
        }
        
        func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
            print("Error \(error.localizedDescription)")
        }
    }
    

    PS:这里最开始添加的city属性用来临时存储定位成功后的信息,应该根据不同的项目需要存储定位信息。我只是用字符串简单的接收而已。
    常规做法至少应该是通过获取的城市名称去服务器(或者本地plist)请求对应的cityId,通过ID的形式存储。

    获取定位:
    @IBAction func getLocation(_ sender: UIButton) {
        let mgr = LocationManager.sharedInstance
        mgr.config()
    }
    

    通过单例调用config方法,获取定位。
    实际项目中,这个步骤大多发生在didFinishLaunchingWithOptions中。

    检查定位权限:

    在实际项目中,由于用户行为的多样,如果项目中的某些功能需要获取定位信息,那你需要提前进行检查。

    func isLocationServiceSuccess(handler: (_ actions: [UIAlertController])->()) -> Bool {
        var arts = [UIAlertController]()
        if !isLocationServiceEnabled() { // 手机定位没开
            // 添加一个alertContrller 跳转手机定位设置
        }
        if !isLocationServiceOpen() { // app定位没开
            let alert = combineAlertController(title: "Location Services Disabled", message: "Please enable Location Services in Settings", open: UIApplication.openSettingsURLString)
            arts.append(alert)
        }
        if arts.count > 0 {
            handler(arts)
            return false
        }
        
        if city == "Undefault" { // 城市获取失败
            config()
        }
        return true
    }
    

    这个方法做了3件事:
    1 判断手机是否开启定位服务,如果没开,则弹窗提示。
    2 判断app是否开启定位服务,如果没开,则弹窗提示。
    3 判断是否保存了正常的定位信息。
    如果以上都通过,则表明检查成功,可以继续调用其他的功能。

    PS:在这个方法中,由于会创建系统的UIAlertController进行弹窗提示,所以需要通过 block 把创建的弹窗对象向外传递。

    调用方法:
    @IBAction func check(_ sender: UIButton) {
        
        let mgr = LocationManager.sharedInstance
        let success = mgr.isLocationServiceSuccess { (alertControllers) in
            for ctrs in alertControllers {
                self.present(ctrs, animated: true, completion: nil)
            }
        }
        print(success)
    }
    

    创建LocationManager单例,并调用isLocationServiceSuccess方法。判断该方法返回值,继续下面的业务需求。

    总结:

    如果你不想过多的引用第三方库让你的项目臃肿不堪,那么很多小功能你都可以尝试自己实现一下。在这个过程中你可以对系统原生SDK有更多的了解,同时再此基础之上也更方便你去阅读优秀的源码。
    我这个定位的demo十分简陋,只是提供一个思路给大家去完善。
    DEMO

    相关文章

      网友评论

          本文标题:Swift 简易定位Demo(基于CLLocationManag

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