为位置隐私而设计
Design for location privacy
2020年6月23日
一句话判断
位置数据是用户最敏感的隐私信息之一——如果你的应用连”为什么需要位置”都解释不清楚,用户根本不会给你权限,这场 Session 教你如何做对。
这场 Session 讲了什么
这场 Session 从设计角度而非纯技术角度探讨了如何在应用中负责任地使用位置数据。iOS 14 引入了两项重大的位置权限变化:精确位置开关(用户可以选择只提供模糊位置)和临时授权(Approximate Location)。这些变化意味着开发者不能再假设拿到的位置是精确的,必须为不同精度级别设计对应的用户体验。
Session 首先回顾了 iOS 位置权限的演变。从”始终允许”到”使用期间允许”,再到 iOS 14 的”仅一次允许”和精确位置开关,Apple 在不断给用户更细粒度的控制权。然后通过几个案例分析,展示了不同类型应用应该如何适配这些变化。比如天气应用只需要城市级别位置就够了,不应该请求精确位置;而导航应用则需要精确位置才能正常工作。
核心建议是”最小权限原则”——只在真正需要时请求位置权限,只请求满足功能所需的最低精度,并且在使用位置数据时向用户透明地解释原因。
值得深挖的点
模糊位置(Approximate Location)的工程影响
当用户关闭精确位置时,CLLocationManager 返回的坐标会被模糊化到约几个街区的精度。你的应用代码不应该崩溃或出现异常行为。Session 建议在 CLLocationManagerDelegate 中检查 location.accuracy 属性,如果精度低于某个阈值就切换到模糊模式 UI。比如外卖应用在模糊位置下应该展示”附近区域”的餐厅列表而非精确定位到具体地址。
权限请求时机的设计策略
Session 强烈反对在应用首次启动时立即弹出位置权限请求。正确的做法是等到用户真正触发需要位置的功能时再请求,比如用户点击了”附近店铺”按钮。同时,权限弹窗前的预备说明(purpose string)必须简洁明确地解释为什么需要位置——“用于推荐附近的咖啡店”比”用于改善用户体验”要好得多。
代码片段
import CoreLocation
class LocationManager: NSObject, CLLocationManagerDelegate {
let manager = CLLocationManager()
func requestLocationIfNeeded() {
// 先检查当前授权状态
let status = manager.authorizationStatus
switch status {
case .notDetermined:
// 首次请求:在用户触发相关功能时才请求
manager.requestWhenInUseAuthorization()
case .authorizedWhenInUse, .authorizedAlways:
// 已授权,开始获取位置
manager.requestLocation()
case .denied, .restricted:
// 被拒绝,引导用户到设置页面手动开启
showLocationDeniedAlert()
default:
break
}
}
func locationManager(_ manager: CLLocationManager,
didUpdateLocations locations: [CLLocation]) {
guard let location = locations.first else { return }
// 检查位置精度,适配模糊位置
if location.horizontalAccuracy > 1000 {
// 精度较低(模糊位置),使用模糊模式
showApproximateMode(with: location.coordinate)
} else {
// 精确位置,正常模式
showPreciseMode(with: location.coordinate)
}
}
}
// 检查和请求精确位置权限
extension LocationManager {
func checkLocationAccuracy() {
if #available(iOS 14, *) {
let accuracy = manager.accuracyAuthorization
switch accuracy {
case .fullAccuracy:
// 用户授予了精确位置权限
print("精确位置已授权")
startPreciseLocationUpdates()
case .reducedAccuracy:
// 用户只授予了模糊位置权限
print("模糊位置模式")
// 如果功能确实需要精确位置,向用户解释
requestTemporaryFullAccuracy()
@unknown default:
break
}
}
}
func requestTemporaryFullAccuracy() {
// 临时精确位置授权:用户可以只为本次操作授权精确位置
let purposeKey = "PreciseLocationForDelivery" // 对应 Info.plist 中的 key
manager.requestTemporaryFullAccuracyAuthorization(
withPurposeKey: purposeKey
) { error in
if let error = error {
print("临时精确位置请求失败: \(error)")
}
}
}
}
// Info.plist 中的位置权限描述配置
/*
<key>NSLocationWhenInUseUsageDescription</key>
<string>用于查找附近的咖啡店并推荐最佳路线</string>
<key>NSLocationTemporaryUsageDescriptionDictionary</key>
<dict>
<key>PreciseLocationForDelivery</key>
<string>配送员需要您的精确位置以确保准时送达</string>
</dict>
*/
最佳实践
- 在请求位置权限前,先用自定义 UI 向用户解释为什么需要位置数据,再触发系统弹窗
- Info.plist 中的
NSLocationWhenInUseUsageDescription要写具体的使用场景,不要写泛泛的描述 - 为模糊位置模式设计独立的 UI 体验,不要在模糊位置下显示精确到门牌号的地址
- 使用 MapKit 的
MKUserTrackingButton让用户主动控制地图跟踪模式,而不是自动跟踪 - 定期审计应用中的位置使用情况,移除不再需要的位置访问代码
还有什么值得关注
- iOS 14 的位置权限弹窗现在默认不选中精确位置复选框,用户需要主动勾选——这会显著降低精确位置授权率
CLLocationManager的新 delegate 方法locationManagerDidChangeAuthorization(_:)可以响应权限状态变化- Session 提到了一个容易被忽略的隐私细节:不要在截图或录屏中暴露用户的精确位置信息