Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> iOS

Cách dùng Swift chạy background để lấy vị trí hiện tại (Background Location)

Để 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

  1. Chọn Project > Target > Signing & Capabilities.
  2. Nhấn + Capability > Background Modes.
  3. 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 = true bắt buộc cho background location (crash nếu false).
  • requestAlwaysAuthorization() cần thiết – WhenInUse khô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.