ใช้ CLLocationManager ขอ Permission Location (Always / When In Use)
Info.plist Keys (จำเป็น)
<key>NSLocationWhenInUseUsageDescription</key>
<string>แอปต้องการตำแหน่งขณะใช้งานเพื่อฟีเจอร์ X</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>แอปต้องการตำแหน่งตลอดเวลาสำหรับ Background Tracking</string>
โค้ดขอ Permission
import CoreLocation
class LocationPermissionManager: NSObject, CLLocationManagerDelegate {
let manager = CLLocationManager()
override init() {
super.init()
manager.delegate = self
}
func requestPermission() {
// เช็คสถานะปัจจุบัน
let status = CLLocationManager.authorizationStatus()
switch status {
case .notDetermined:
// ยังไม่ได้ขอ → ขอ WhenInUse ก่อน (Best Practice)
manager.requestWhenInUseAuthorization()
case .authorizedWhenInUse:
// มี WhenInUse แล้ว → ขอ Always ถ้าจำเป็น
manager.requestAlwaysAuthorization()
case .authorizedAlways:
print("✅ Already authorized Always")
startLocationUpdates()
case .denied, .restricted:
print("❌ Denied - นำผู้ใช้ไป Settings")
openSettings()
@unknown default: break
}
}
func startLocationUpdates() {
guard CLLocationManager.locationServicesEnabled() else { return }
manager.startUpdatingLocation()
}
// Delegate: สถานะเปลี่ยน
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
requestPermission() // เช็คซ้ำ
}
func openSettings() {
guard let url = URL(string: UIApplication.openSettingsURLString) else { return }
UIApplication.shared.open(url)
}
}
Authorization Status Enum
.notDetermined- ยังไม่ได้ขอ.restricted- ถูกจำกัด (Parental Control, MDM).denied- ผู้ใช้ปฏิเสธ.authorizedWhenInUse- อนุญาตขณะใช้งาน.authorizedAlways- อนุญาตตลอดเวลา (Background)
Best Practice Flow
- ขอ WhenInUse ก่อน (User Trust สูงกว่า)
- เมื่อต้องการ Background → ขอ Always ทีหลัง
- อธิบายเหตุผลชัดเจนใน Info.plist Description
- Handle Denied: นำไป Settings App
ตรวจสอบ Location Services เปิดอยู่หรือไม่
if CLLocationManager.locationServicesEnabled() {
print("Location Services: ON")
} else {
print("Location Services: OFF - นำไป Settings > Privacy > Location Services")
}