Để lấy vị trí (location) khi app ở background trong Swift, cần cấu hình quyền, bật background mode, và dùng CLLocationManager đúng cách.
1. Cấu hình Info.plist (Quyền)
Thêm 2 key (bắt buộc iOS 11+):
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>App cần vị trí luôn để theo dõi đường đi</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>App cần vị trí khi đang dùng</string>
2. Bật Background Modes trong Xcode
- Chọn Project > Target > Signing & Capabilities.
- Nhấn + Capability > Background Modes.
- Tích Location updates.
3. Code CoreLocation
import CoreLocation
class LocationManager: NSObject, CLLocationManagerDelegate {
static let shared = LocationManager()
private let manager = CLLocationManager()
private override init() {
super.init()
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.distanceFilter = 10 // Cập nhật khi di chuyển > 10m
manager.allowsBackgroundLocationUpdates = true // Quan trọng!
manager.pausesLocationUpdatesAutomatically = false // Không tạm dừng tự động
}
func startTracking() {
// Xin quyền
manager.requestAlwaysAuthorization()
// Bắt đầu cập nhật
manager.startUpdatingLocation()
// Hoặc significant location changes (tiết kiệm pin hơn)
// manager.startMonitoringSignificantLocationChanges()
}
// Delegate
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let location = locations.last else { return }
print("Location updated: \(location.coordinate.latitude), \(location.coordinate.longitude)")
// Gọi API gửi vị trí lên server
// sendLocationToServer(location)
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
switch status {
case .authorizedAlways:
print("Đã cấp quyền Always")
manager.startUpdatingLocation()
case .authorizedWhenInUse:
print("Chỉ cấp When In Use - background location không hoạt động")
case .denied, .restricted:
print("User từ chối quyền vị trí")
default:
break
}
}
}
4. Gọi trong AppDelegate / SceneDelegate
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
LocationManager.shared.startTracking()
return true
}
Lưu ý quan trọng
allowsBackgroundLocationUpdates = truebắt buộc cho background location (crash nếu false).requestAlwaysAuthorization() cần thiết –WhenInUsekhông cho background.- Test trên thiết bị thật (Simulator không mô phỏng background location tốt).
- Tiết kiệm pin: Dùng
startMonitoringSignificantLocationChanges()thay vìstartUpdatingLocation()nếu không cần độ chính xác cao liên tục. - iOS 13+: User có thể chọn "Allow Once", "While Using", "Always" – handle tất cả cases.