I'm using CloudKit to sync data between devices. Everything looks fine (Data was changed -> push notification with record id -> fetch/edit/delete this record in cloud and local coredata db) if app is an active. But when I press "Home" button it just doesn't work. Here is my code:
Create subscriptions when app is launched in first time
func addNewRecordsSub() {
let subscription = CKSubscription(recordType: "UserRecords", predicate: predicate, options: [.FiresOnRecordCreation, .FiresOnRecordUpdate, .FiresOnRecordDeletion])
let notificationInfo = CKNotificationInfo()
notificationInfo.shouldBadge = false
subscription.notificationInfo = notificationInfo
let privateDatabase = container.privateCloudDatabase
privateDatabase.saveSubscription(subscription) { subscription, error in
if error != nil {
print(error)
}
NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in
self.addNewRecordCategoriesSub()
})
}
}
func addNewRecordCategoriesSub() {
let subscription = CKSubscription(recordType: "UserRecordsCategories", predicate: predicate, options: [.FiresOnRecordCreation, .FiresOnRecordUpdate, .FiresOnRecordDeletion])
let notificationInfo = CKNotificationInfo()
notificationInfo.shouldBadge = false
subscription.notificationInfo = notificationInfo
let privateDatabase = container.privateCloudDatabase
privateDatabase.saveSubscription(subscription) { subscription, error in
if error != nil {
print(error)
}
NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in
self.performSegueWithIdentifier("goToRootController", sender: self)
})
}
}
AppDelegate
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
UINavigationBar.appearance().barStyle = .Black
//Push
let notificationTypes: UIUserNotificationType = [UIUserNotificationType.Alert]
let pushNotificationSettings = UIUserNotificationSettings(forTypes: notificationTypes, categories: nil)
application.registerUserNotificationSettings(pushNotificationSettings)
application.registerForRemoteNotifications()
if let options: NSDictionary = launchOptions {
let remoteNotification = options.objectForKey(UIApplicationLaunchOptionsRemoteNotificationKey) as? NSDictionary
if let notification = remoteNotification {
self.application(application,
didReceiveRemoteNotification: notification as! [NSObject : AnyObject])
}
}
return true
}
func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
print("DEVICE TOKEN = \(deviceToken)")
}
func application(application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: NSError) {
print(error)
}
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
let ckNotification = CKNotification(fromRemoteNotificationDictionary: userInfo as! [String : NSObject])
if ckNotification.notificationType == .Query {
let queryNotification = ckNotification as! CKQueryNotification
let recordID = queryNotification.recordID!
//Saving/Update/delete record
}
Update: Ok, i found it https://developer.apple.com/library/mac/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/TheNotificationPayload.html
The aps dictionary can also contain the content-available property. The content-available property with a value of 1 lets the remote notification act as a silent notification. When a silent notification arrives, iOS wakes up your app in the background so that you can get new data from your server or do background information processing. Users aren’t told about the new or changed information that results from a silent notification, but they can find out about it the next time they open your app.
For a silent notification, take care to ensure there is no alert, sound, or badge payload in the aps dictionary. If you don’t follow this guidance, the incorrectly-configured notification might be throttled and not delivered to the app in the background, and instead of being silent is displayed to the user.
Now it works like: press home button -> open app again -> get new data.
let subscription = CKSubscription(recordType: "UserRecords", predicate: self.predicate, options: [.FiresOnRecordCreation, .FiresOnRecordUpdate, .FiresOnRecordDeletion])
let notificationInfo = CKNotificationInfo()
notificationInfo.shouldBadge = false
notificationInfo.shouldSendContentAvailable = true
subscription.notificationInfo = notificationInfo
let privateDatabase = self.container.privateCloudDatabase
privateDatabase.saveSubscription(subscription) { subscription, error in
if error != nil {
print(error)
}
NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in
self.addNewRecordCategoriesSub()
})
}
But I see another problem. I can't get data if I close app (double click on home and swipe). Is it me or iOS doesn't support it?