CloudKit subscriptions when app is closed

Viewed 664

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?

0 Answers
Related