这是一个简易的一次性定位工具的封装,基于系统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
网友评论