Swift 3或4中无需调用CLLocationManager代理didUpdateLocations如何获取当前位置?
在Swift 3/4中无需依赖
didUpdateLocations获取当前位置的方法 嘿,这个问题问得很到位!在Swift 3和4的开发环境里,确实存在不用手动实现CLLocationManager的didUpdateLocations代理方法就能获取设备当前位置的方式,我给你分享两个实用的方案:
1. 封装闭包式的实时位置获取
我们可以把CLLocationManager的代理逻辑封装到扩展里,对外暴露一个闭包回调,这样外部调用时完全不用关心代理方法的实现。代码示例如下:
import CoreLocation extension CLLocationManager { /// 获取当前实时位置,通过闭包返回结果 func fetchCurrentLocation(completion: @escaping (CLLocation?, Error?) -> Void) { // 用私有代理类处理回调 self.delegate = LocationCallbackDelegate(completion: completion) // 请求位置权限(根据你的需求选WhenInUse或Always) self.requestWhenInUseAuthorization() // 发起单次位置请求 self.requestLocation() } } /// 私有代理类,处理位置回调逻辑 private class LocationCallbackDelegate: NSObject, CLLocationManagerDelegate { private let completionHandler: (CLLocation?, Error?) -> Void init(completion: @escaping (CLLocation?, Error?) -> Void) { self.completionHandler = completion super.init() } func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { // 取第一个最新的位置 guard let latestLocation = locations.first else { completionHandler(nil, NSError(domain: "LocationFetchError", code: -1, userInfo: [NSLocalizedDescriptionKey: "未获取到有效位置"])) return } completionHandler(latestLocation, nil) // 拿到位置后停止更新 manager.stopUpdatingLocation() } func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) { completionHandler(nil, error) manager.stopUpdatingLocation() } }
调用的时候非常简单,不用实现任何代理方法:
let locationManager = CLLocationManager() locationManager.fetchCurrentLocation { location, error in if let location = location { print("实时位置:纬度\(location.coordinate.latitude),经度\(location.coordinate.longitude)") } else if let error = error { print("获取位置失败:\(error.localizedDescription)") } }
这个方案的优势在于:把代理逻辑完全封装起来,代码更整洁,外部调用更直观,而且能保证拿到的是实时的最新位置。
2. 直接读取缓存位置
如果你对位置的时效性要求不高,可以直接访问CLLocationManager的location属性,这个属性会返回设备最近缓存的位置:
let locationManager = CLLocationManager() // 先请求权限(必须步骤) locationManager.requestWhenInUseAuthorization() if let cachedLocation = locationManager.location { print("缓存位置:纬度\(cachedLocation.coordinate.latitude),经度\(cachedLocation.coordinate.longitude)") } else { print("没有可用的缓存位置") }
⚠️ 注意:这个方法的局限性很明显——如果设备很久没获取过位置,或者位置缓存已经过期,location属性会返回nil,而且无法保证是当前的实时位置,所以只适合快速获取大致位置的场景。
重要提醒
不管用哪种方式,都必须在Info.plist中添加对应的权限描述键:
- 如果你用
requestWhenInUseAuthorization(),需要添加NSLocationWhenInUseUsageDescription,并填写权限申请说明 - 如果你用
requestAlwaysAuthorization(),需要添加NSLocationAlwaysUsageDescription
否则App会直接崩溃哦!
内容的提问来源于stack exchange,提问作者Adriel Artiza
相关产品推荐
相关产品推荐

