Search code examples
iosswiftxcodebackgroundcloudkit

CloudKit - How to modify the record in the background


My App can use location updates in the background now. Then, can we modify the record in the background when a user is moving?

Code:

@IBOutlet weak var mapView: MKMapView!
var locationManager: CLLocationManager!


override func viewDidLoad() {
    super.viewDidLoad()

    mapView.delegate = self

    locationManager = CLLocationManager()
    locationManager.delegate = self

    locationManager.requestAlwaysAuthorization()
    locationManager.startUpdatingLocation()
    locationManager.allowsBackgroundLocationUpdates = true

}


func locationManager(_ manager: CLLocationManager, didUpdateLocations locations:[CLLocation]) {
    recordLocation()   
}


func recordLocation() {

    let publicDatabase = CKContainer.default().publicCloudDatabase

    let predicate = NSPredicate(format: "accountID == %@", argumentArray: [myID!])
    let query = CKQuery(recordType: "Accounts", predicate: predicate)

    publicDatabase.perform(query, inZoneWith: nil, completionHandler: {(records, error) in

        if let error = error {
            print("error1: \(error)")
            return
        }

        for record in records! {

            record["currentLocation"] = self.mapView.userLocation.location

            publicDatabase.save(record, completionHandler: {(record, error) in

                if let error = error {
                    print("error2: \(error)")
                    return
                }
                print("success!")
            })
        }
    })
}

image - Capability of Background Modes

By the way, everything is fine as long as my app runs in the foreground.

Versions

Xcode 12.2 / Swift 4.2

Summary

Could you please tell me how to modify the record in the background? In the first place, can we do that?

Thanks.


Solution

  • I misunderstood. I had already recorded my location in the background, but had failed to get the latest one.

    record["currentLocation"] = self.mapView.userLocation.location
    

    By using this code, I had recorded the location the last moment that I were viewing MKMapView.

    In other words, the problem, recording in the background, have been solved from the beginning.

    I rewrote as the following code:

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations:[CLLocation]) {
    
        if let location = locations.first {
            recordLocation(currentLocation: location)
        }
    
    }
    
    
    func recordLocation(currentLocation: CLLocation) {
    
        let publicDatabase = CKContainer.default().publicCloudDatabase
    
        let predicate = NSPredicate(format: "accountID == %@", argumentArray: [myID!])
        let query = CKQuery(recordType: "Accounts", predicate: predicate)
    
        publicDatabase.perform(query, inZoneWith: nil, completionHandler: {(records, error) in
    
            if let error = error {
                print("error1: \(error)")
                return
            }
    
            for record in records! {
    
                record["currentLocation"] = currentLocation as CLLocation
    
                publicDatabase.save(record, completionHandler: {(record, error) in
    
                    if let error = error {
                        print("error2: \(error)")
                        return
                    }
                    print("success!: \(String(describing: currentLocation))")
                })
            }
        })
    
    }