App 需要根據用戶是否授權定位權限,決定顯示不同的視圖控制器(如:授權顯示地圖頁、拒絕顯示手動輸入頁)。
import CoreLocation
class LocationPermissionHandler: NSObject, CLLocationManagerDelegate {
private let locationManager = CLLocationManager()
private var onPermissionResult: ((Bool) -> Void)?
override init() {
super.init()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
}
func requestPermission(completion: @escaping (Bool) -> Void) {
onPermissionResult = completion
let status = CLLocationManager.authorizationStatus()
switch status {
case .notDetermined:
locationManager.requestWhenInUseAuthorization() // 或 requestAlwaysAuthorization()
case .restricted, .denied:
completion(false)
case .authorizedWhenInUse, .authorizedAlways:
completion(true)
@unknown default:
completion(false)
}
}
// MARK: - CLLocationManagerDelegate
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
switch status {
case .authorizedWhenInUse, .authorizedAlways:
onPermissionResult?(true)
case .denied, .restricted:
onPermissionResult?(false)
default:
break
}
onPermissionResult = nil // 防止重複回調
}
// 兼容舊版 iOS:didFailWithError 也會在拒絕時觸發
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
if let clError = error as? CLError, clError.code == .denied {
onPermissionResult?(false)
onPermissionResult = nil
}
}
}
| 錯誤代碼 | 常數名稱 | 含義 |
|---|---|---|
| 0 | kCLErrorLocationUnknown | 位置暫時未知,繼續嘗試 |
| 1 | kCLErrorDenied | 用戶拒絕定位權限 |
| 2 | kCLErrorNetwork | 網路相關錯誤 |
| 3 | kCLErrorHeadingFailure | 無法取得方向 |
| 4 | kCLErrorRegionMonitoringDenied | 區域監測被拒絕 |
| ... | ... | ... |
class MainViewController: UIViewController {
private let permissionHandler = LocationPermissionHandler()
override func viewDidLoad() {
super.viewDidLoad()
checkLocationPermission()
}
private func checkLocationPermission() {
permissionHandler.requestPermission { [weak self] granted in
DispatchQueue.main.async {
if granted {
self?.showMapViewController()
} else {
self?.showManualInputViewController()
}
}
}
}
private func showMapViewController() {
let mapVC = MapViewController()
navigationController?.pushViewController(mapVC, animated: true)
}
private func showManualInputViewController() {
let manualVC = ManualLocationInputViewController()
navigationController?.pushViewController(manualVC, animated: true)
}
}
<key>NSLocationWhenInUseUsageDescription</key>
<string>我們需要您的位置來顯示附近的店家資訊</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>我們需要您的位置來提供背景導航功能</string>
func openAppSettings() {
guard let settingsUrl = URL(string: UIApplication.openSettingsURLString) else { return }
if UIApplication.shared.canOpenURL(settingsUrl) {
UIApplication.shared.open(settingsUrl, options: [:], completionHandler: nil)
}
}
// 在拒絕處理中呼叫
let alert = UIAlertController(
title: "需要定位權限",
message: "請在設定中開啟定位權限以使用完整功能",
preferredStyle: .alert
)
alert.addAction(UIAlertAction(title: "去設定", style: .default) { _ in
self.openAppSettings()
})
alert.addAction(UIAlertAction(title: "取消", style: .cancel))
present(alert, animated: true)
使用 CLLocationManagerDelegate 的 didChangeAuthorization 方法可即時偵測授權狀態變化。iOS 14+ 新增 authorizedWhenInUse 與 authorizedAlways 細分,建議優先請求 WhenInUse 權限。拒絕時應友善引導用戶至設定頁,而非單純阻擋功能。