I followed the tutorial by google on https://firebase.google.com/docs/notifications/ios/console-topics#receive_and_handle_topic_messages to subscribe to a Firebase topic on my iOS app.
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool {
FIRMessaging.messaging().subscribeToTopic("/topics/Notifications")
let homeViewController = UINavigationController(rootViewController: HomeViewController())
UINavigationBar.appearance().translucent = false
window = UIWindow(frame: UIScreen.mainScreen().bounds)
window?.rootViewController = homeViewController
window?.makeKeyAndVisible()
return true
}
However, when I send a topic push notification out from the Firebase console. I could not receive any push notifications. But when I send out push notification to user segment from the console, the push is working perfectly. When I check the Xcode console, I am seeing this FIRMessaging error.
2016-05-31 11:11:47.893: <FIRMessaging/WARNING> Cannot subscribe to topic: /topics/Notifications with token: (null)
I've tried to search for this error but have no luck finding anything. I am not sure if this is the problem that is causing my app to not receive any push from topics.
Does anyone have this issue and know how to solve it?
Looks like maybe you're calling subscribeToTopic too early.
First, before you set up any Firebase call, make sure you call
FIRApp.configure()
That will ensure that all Firebase services are properly set up and initialized.
Next, you're going to need to wait just a bit to subscribe to topics. Your client needs to first register your app with both APNs and FCM to ensure that it can receive notifications. That involves a network call, which means you can't subscribe to topics when your app first launches.
Instead, I'd recommend putting that code into your application:didRegisterUserNotificationSettings handler instead. Something like this:
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
NSLog(#"Hooray! I'm registered!");
[[FIRMessaging messaging] subscribeToTopic:#"/topics/cool_users"];
}
Edit: And the Swift version...
func application(application: UIApplication, didRegisterUserNotificationSettings notificationSettings: UIUserNotificationSettings) {
print("Hooray! I'm registered!")
FIRMessaging.messaging().subscribeToTopic("/topics/swift_fans")
}
The accepted solution did not work for me. The token is not always available when application:didRegisterUserNotificationSettings: is called.
For example if application is freshly installed and starts for the first time FIRInstanceID.instanceID().token() returns nil.
You need to make sure application calls subscribeToTopic: after the token is available.
I ended up with creating a helper object that enqueues subscribeToTopic:, unsubscribeFrom: calls and executes them in FIFO order after the token arrives.
class FIRMessagingHelper {
private let queue: OperationQueue
init() {
queue = OperationQueue()
queue.maxConcurrentOperationCount = 1
queue.addOperation(TokenReadyOperation())
}
func subscribeTo(topic: String) {
queue.addOperation {
OperationQueue.main.addOperation({
FIRMessaging.messaging().subscribeToTopic(topic)
})
}
}
func unsubscribeFrom(topic: String) {
queue.addOperation {
OperationQueue.main.addOperation({
FIRMessaging.messaging().unsubscribeFromTopic(topic)
})
}
}
}
TokenReadyOperation waits until the token appears. AsynchronousOperation is used as the base class to minimize boilerplate.
class TokenReadyOperation : AsynchronousOperation {
override init() {
super.init()
NotificationCenter.default.addObserver(self,
selector: #selector(TokenReadyOperation.tokenRefreshed(notification:)),
name: .firInstanceIDTokenRefresh,
object: nil)
}
override func didStart() {
finishIfTokenAvailable()
}
private func finishIfTokenAvailable() {
guard FIRInstanceID.instanceID().token() != nil else { return }
markFinished()
}
/// Posted every time token changes
#objc private func tokenRefreshed(notification: Notification) {
finishIfTokenAvailable()
}
}
Few things to keep in mind:
App must call FIRApp.configure() or FIRApp.configureWithOptions(_:) prior making any Firebase calls (as Todd Kerpelman mentioned)
subscribeToTopic:, unsubscribeFrom: are not thread safe and must be executed on main thread
Topic names has to be in "/topics/*" format (as henmer mentioned)
Make sure to use different configuration plist for debug and App Store release of your app. See FIRApp.configureWithOptions(_:) documentation.
Date & Time should be current, otherwise the token may not be delivered.
Make sure to use the newest framework version. I had issues with notification delivery with the SDK released around January 2017.
My problem was not solved by calling subscribeToTopic after
func application(application: UIApplication, didRegisterUserNotificationSettings notificationSettings: UIUserNotificationSettings) {
instead it worked by calling subscribeToTopic after
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
this function get called when you get your push token from APNS not firebase.
Xcode 8.3.2
Swift 3.0
Related
I am setting up Firebase Cloud Messaging to send notifications to an iOS app.
And I want to be able to send notifications, to all users who accepted to receive them.
After reading and experimenting quite a bit, my understanding is that (for my use case) I should set up some kind of general topic and then send each notification to this topic.
My question is: how to create a topic first, and then how to register (a client) to a topic in my iOS Swift app?
Though I tried to browse the net for info on that, I did not find much.
For information, I am using Xcode Version 10.1, iOS 12.1 and Swift 4.2.
Step 1: Setting Up Firebase
If you have yet to add Firebase to your project, it's all documented here:
https://firebase.google.com/docs/ios/setup
You will need to start the configuration of Firebase. For my project, I started the configuration in the AppDelegate upon app start.
class AppDelegate: UIResponder, UIApplicationDelegate, MessagingDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
Messaging.messaging().delegate = self
...
}
...
}
Step 2: Requesting Authorization
Assuming you have all the APNs Authentication Key/Certificates configured on your Apple Developer Portal and Firebase Cloud Messaging settings,
https://developer.apple.com/account/ios/certificate/
https://console.firebase.google.com/u/0/project/FIREBASE_PROJECT_NAME/settings/cloudmessaging/ios:APP_BUNDLE_ID
Next, you will need to request authorization for Push Notifications on the device. I've placed this in one of the first few UIViewControllers my project.
class FirstViewController: UIViewController {
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound], completionHandler: { (success, error) in
guard success else { return }
UIApplication.shared.registerForRemoteNotifications()
})
}
}
Step 3: Device Token
Upon registering for remote notification in step 2 with:
UIApplication.shared.registerForRemoteNotifications()
You will need to implement this delegate function in your AppDelegate:
class AppDelegate: UIResponder, UIApplicationDelegate, MessagingDelegate {
...
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
Messaging.messaging().apnsToken = deviceToken.reduce("", {$0 + String(format: "%02X", $1)})
}
...
}
Do note that the deviceToken received is in NSData, and the apnsToken required by Firebase is in String.
Step 4: Topic Subscription
Remember the delegate reference we set to AppDelegate in step 1?
Messaging.messaging().delegate = self
You will need to implement its delegate function to let the app know that it Firebase did receive the token and it is ready to subscribe to a topic.
class AppDelegate: UIResponder, UIApplicationDelegate, MessagingDelegate {
...
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
Messaging.messaging().subscribe(toTopic: "/topics/example")
}
...
}
Step 5: Validation
One simple way to check if your app has successfully subscribed to a topic is to send a push notification via Firebase Console.
https://console.firebase.google.com/u/0/project/FIREBASE_PROJECT_NAME/notification
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I want to make a request when the application enters the onBackground or onAppWillTerminate mode. I added an observer to AppDelegate method but did not work. Simply I want to send a request and push notification as a response. How can I do this? My request is not news or music, simple JSON.
`func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
Fabric.with([Crashlytics.self])
GADMobileAds.configure(withApplicationID: "ca-app-pub-8446699920682817~7829108")
let onesignalInitSettings = [kOSSettingsKeyAutoPrompt: false]
//ONE SIGNAL
OneSignal.initWithLaunchOptions(launchOptions,
appId: "f5854e88-0b58-495f-8d3f-e7899202d",
handleNotificationAction: nil,
settings: onesignalInitSettings)
OneSignal.inFocusDisplayType = OSNotificationDisplayType.notification;
OneSignal.promptForPushNotifications(userResponse: { accepted in
print("User accepted notifications: \(accepted)")
})
UIApplication.shared.statusBarStyle = .lightContent
UIApplication.shared.setMinimumBackgroundFetchInterval(UIApplicationBackgroundFetchIntervalMinimum)
mS.StartTimer()
//NotificationCenter.default.addObserver(self, selector:#selector(AppDelegate.applicationWillTerminate(_:)), name:NSNotification.Name.UIApplicationWillTerminate, object:nil)
NotificationCenter.default.addObserver(self, selector:#selector(AppDelegate.applicationWillEnterForeground(_:)), name:NSNotification.Name.UIApplicationWillEnterForeground, object:nil)
return true
}
func applicationWillTerminate(_ application: UIApplication) {
//mS.StartTimer()
}
func application(_ application: UIApplication, performFetchWithCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
self.mS.StartTimer()
if let vc = window?.rootViewController as? LiveScores{
vc.getLiveMatches(url : URL(string: "http://test.com/test/index.php/Service/lastLive"))
}
completionHandler(.newData)
}
func application(_ application: UIApplication,
didReceiveRemoteNotification userInfo: [AnyHashable : Any],
fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void){
completionHandler(UIBackgroundFetchResult.newData)
}
func applicationDidEnterBackground(_ application: UIApplication) {
if let vc = window?.rootViewController as? LiveScores{
vc.getLiveMatches(url : URL(string: "http://opucukgonder.com/tipster/index.php/Service/lastLive"))
}
mS.StartTimer()
}
func applicationWillEnterForeground(_ application: UIApplication) {
if let vc = window?.rootViewController as? LiveScores{
vc.getLiveMatches(url : URL(string: "http://opucukgonder.com/tipster/index.php/Service/lastLive"))
}
mS.StartTimer()
}
}`
Actually application is forcefully killed after 3-4 seconds when applicationWillTerminate is called.
so thats why API is not called.
One solution you can try is to add sleep at the end of the applicationWillTerminate function like this :
func applicationWillTerminate(_ application: UIApplication) {
//call API Here
// 5 is the number of seconds in which you estimate your request
// will be finished before system terminate the app process
sleep(5)
print("applicationWillTerminate")
}
If you want to contact the server when the app is going into the background, that is certainly possible. Implement UIApplicationDelegate.applicationDidEnterBackground. See Strategies for Handling App State Transitions for full details. This is a very common and supported operation and should be what you need.
However, it is not possible to contact the server when the app is killed in the background. applicationWillTerminate is generally never called in any case since iOS 4. Prior to iOS 4, there was no "background" mode. When the user pressed the home button, the app was immediately terminated after calling this method, and that's why it still exists. But it's all-but-useless in modern apps. (You can still get this ancient behavior by setting UIApplicationExitsOnSuspend in your Info.plist, but this does nothing to help your problem.)
When your application is killed in the background it is just killed. It is not woken up, and no methods are called on it. It is unceremoniously terminated and removed from memory. You cannot respond to this event. The same happens when the user force-quits your app from the app-switcher.
I'm a little curious about why you would want a push notification when the app goes into the background, and particularly when the app terminates. When I've seen people try to do this in the past, they often were trying to use push notifications to keep the app launched at all times. This is not possible. Even if you found a work-around to make it technically possible, it is explicitly forbidden by Apple.
For Swift3 / iOS10 see this link:
ios10, Swift 3 and Firebase Push Notifications (FCM)
I'm trying to use the Firebase for Notifications and I integrated it exactly as described in the docs.
But I don't understand why is doesn't work. When I build my project I see this line:
2016-05-25 16:09:34.987: <FIRInstanceID/WARNING> Failed to fetch default token Error Domain=com.firebase.iid Code=0 "(null)"
This my AppDelegate:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
FIRApp.configure()
FIRDatabase.database().persistenceEnabled = true
var service: DataService = DataService()
service.start()
registerForPushNotifications(application)
application.registerForRemoteNotifications()
return true
}
func registerForPushNotifications(application: UIApplication) {
let notificationSettings = UIUserNotificationSettings(
forTypes: [.Badge, .Sound, .Alert], categories: nil)
application.registerUserNotificationSettings(notificationSettings)
}
func application(application: UIApplication, didRegisterUserNotificationSettings notificationSettings: UIUserNotificationSettings) {
if notificationSettings.types != .None {
application.registerForRemoteNotifications()
}
}
func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
let tokenChars = UnsafePointer<CChar>(deviceToken.bytes)
var tokenString = ""
for i in 0..<deviceToken.length {
tokenString += String(format: "%02.2hhx", arguments: [tokenChars[i]])
}
FIRInstanceID.instanceID().setAPNSToken(deviceToken, type: FIRInstanceIDAPNSTokenType.Unknown)
print("Device Token:", tokenString)
}
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
// Print message ID.
print("Message ID: \(userInfo["gcm.message_id"]!)")
// Print full message.
print("%#", userInfo)
}
I too had the same issue and nothing worked for me. But all you have to do is go to your firebase console and then find your project and goto its settings, there check in its cloud messaging tab and upload your .p12 certificate into that.
thats it! happy coding :)
1.Set Notification Observer in didFinishLaunchingWithOptions Method
2.And Set tokenRefreshNotification method then u get Token in this method.
See below Code
import Firebase
import FirebaseMessaging
override func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
FIRApp.configure()
NotificationCenter.default.addObserver(self,
selector: #selector(self.tokenRefreshNotification(notification:)),
name: NSNotification.Name.firInstanceIDTokenRefresh,
object: nil)
}
// NOTE: Need to use this when swizzling is disabled
public func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
FIRInstanceID.instanceID().setAPNSToken(deviceToken, type: FIRInstanceIDAPNSTokenType.Sandbox)
}
func tokenRefreshNotification(notification: NSNotification) {
// NOTE: It can be nil here
let refreshedToken = FIRInstanceID.instanceID().token()
print("InstanceID token: \(refreshedToken)")
connectToFcm()
}
func connectToFcm() {
FIRMessaging.messaging().connectWithCompletion { (error) in
if (error != nil) {
print("Unable to connect with FCM. \(error)")
} else {
print("Connected to FCM.")
}
}
}
public func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
print(userInfo)
}
1 - Have you correctly configured your certificates as specified in the google documentation ( I won't recall the process here, it is quite long... )?
( https://firebase.google.com/docs/cloud-messaging/ios/certs#configure_an_app_id_for_push_notifications )
2 - I've been through some difficulties when setting up FCM. Once I thought everything was ok but notifications were still not working, I've decided to completely remove the app from the phone, clean my build folder and reinstall the whole thing. After that, it was working.
3 - The app was receiving notifications, but I was still getting the "Failed to fetch default token..." message. It disappeared after a while. Don't ask me why!
This is not really a proper answer, I just share my experience because I know configuring notification is not easy and every clue is welcome. So maybe this one can help. Cheers :)
After trying all of the above (and anything I could find elsewhere), what resolves the problem for me is to move
let token = FIRInstanceID.instanceID().token()
to be called when pressing a button, and not on app loading.
I know it's probably not the most elegant solution, but it's good enough for debugging purposes.
Im guessing the token is not available immediately by the server, and takes some time to be generated.
The answers above cover most of the issue, but I had the same issue and I found the following info useful:
Firebase can 'rotate' (change) a user's FCM token at any time. This is the 128 character ID that your server will use to send the push notification to the device.
Firebase docs say best practice is to use a delegate to monitor for changes with the delegate callback method:
- (void)messaging:(nonnull FIRMessaging *)messaging didRefreshRegistrationToken:(nonnull NSString *)fcmToken
[Obj - C]
func messaging(_ messaging: Messaging, didRefreshRegistrationToken fcmToken: String)
[Swift]
The delegate method should be called on every change, at which point you can update the record in your server.
Unfortunately that wasn't working for me, I had a delegate but the callback wasn't being invoked. So I had to resort to manually updating the token on each app launch (as suggested by #micheal chein above) as follows:
NSString *deviceToken = [FIRInstanceID instanceID].token; // Send this to your server
[Obj-C]
let token = FIRInstanceID.instanceID().token() // Send this to your server
[Swift]
** Important: update the token after a delay (20-25s), as the rotation can sometimes only reflect after some time. You can use a timer for this.
After this I still get the APNS warning/error message:
2017-06-06 09:21:49.520: <FIRInstanceID/WARNING> Failed to fetch APNS token Error Domain=com.firebase.iid Code=1001 "(null)"
BUT, push notifications work every time without fail. So I think that log message is a bit off (possibly mistimed). If you can get option 2 to work for you, definitely do that!
FCM was working for me then just stopped. I did what Rabs G. suggested and removed the app and installed again and the notifications started working again.
i want to know if it is possible to launch a background process in iOS. In my background process every 30 minutes there should a function get called, in order to check in my database if there are new messages, etc in order to send a notification. I don't want to implement push notifications.
I don't know where to implement this feature, and if there are override functions e.g. in the AppDelegate.
Thanks for your help,
hannes
What you want is called "Background Fetch" and is available starting from iOS 7:
https://www.objc.io/issues/5-ios7/multitasking/
Yes it is possible to launch a background process in iOS. It is also possible to launch this process every 30 minutes. You need to setup two things! You need to send every 30 minutes a silent Push with your server.(e.g. with a Cloud Code job in Parse(Warning! Since Parse will be shutdowned in January 2017, it is not clever working on this platform)
This silent push initiate an NSURLBackgroundSession which pulls the desired data from your server and process it.
Your need to activate this in the project settings
1.) Add this in AppDelgate for receiving pushes
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool
{
application.registerForRemoteNotifications()
}
When you get a push from a server or something else, following delegate method will be called: (so add this too in your appDelegate)
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void)
{
NSLog("Silent Push recevied")
let vc = ViewController()
vc.pullData() // call your pullData method...
}
The method which is called now needs to pull the data from your database. In this case you use a NSURLSession to download whatever you need.
2.) Go to the ViewController where the data get processed and add:
the NSURLSessionDownloadDelegate delegate with the required delegate methods
class vc : ViewController, NSURLSessionDownloadDelegate{
func viewDidLoad()
{
super.viewDidLoad()
}
func pullData()
{
let url = NSURL(string: "http://example.com")!
let urlRequest = NSURLRequest(URL: url, cachePolicy: .UseProtocolCachePolicy, timeoutInterval: 5)
let backgroundSessionConfiguration = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier("backgroundSessionIDX")
backgroundSession = NSURLSession(configuration: backgroundSessionConfiguration, delegate: self, delegateQueue: NSOperationQueue.mainQueue())
let task = backgroundSession.downloadTaskWithRequest(urlRequest)
task.resume()
}
}
When the downloadTask is successfully completed
func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didFinishDownloadingToURL location: NSURL)
{
}
will be called and you can process the data
let path = location.path
let data = NSFileManager.defaultManager().contentsAtPath(path!)
You can alternatively do this with a NSURLSessionDataTask
I would recommend that you take a look at Apple's documentation on Background Execution. It states all the possible ways to run code in the background. Each method comes with it's limitations, advantages and disadvantages and also Apple mentions:
In iOS, only specific app types are allowed to run in the background
If your iOS application does not communicate over Bluetooth (BTLE or with MFi certified devices) with some device (you could configure that Bluetooth device to send some event to the iOS device every 30 minutes and execute your code when that happens), then the most reliable way to run some code every 30 minutes is by using silent push notifications.
Silent push notifications can be configured so that they're not shown to the user, but allows your code to run. The limitations with push notifications are that the user needs an active internet connection to receive them and the user needs to give your app permission to use push notifications (you can request this at app's first run).
I noticed that your questions mentions I don't want to use push notifications, but unfortunately you don't really have a choice here.
For background
In your viewDidLoad() method
let notificationCenter = NotificationCenter.default
notificationCenter.addObserver(self, selector: #selector(appMovedToBackground), name: UIApplication.didEnterBackgroundNotification, object: nil)
Add this method in your ViewController
#objc func appMovedToBackground() {
print("App moved to background!")
}
For Forground
override func viewDidLoad() {
super.viewDidLoad()
let notificationCenter = NotificationCenter.default
notificationCenter.addObserver(self, selector: #selector(appMovedToForground), name: UIApplication.willEnterForegroundNotification, object: nil)
}
#objc func appMovedToForground() {
print("App moved to forground!")
}
EDIT:
Retested today 27.08.2015 and it works again, Apple has fixed it.
I have an application in development mode. The application uses CKSubscription to get notified on changes on the server, configured for all three options: create, update, delete. Everything was working fine but recently during regression tests I have discovered the application does not receive notifications on record updates, the create and delete notifications are still working. The susbcription types are set correctly for all three options as I checked on the dashboard and the application is registered for CKSubscription as it was a couple of days ago when it was working like charm. I am not getting any errors from CloudKit. The reset of development environment did not help. I have re-tested with the version with which I am sure it was working and got the same results.
Any idea what might be causing this issue, what else should I check / try?
Additional Info:
I guess something might go wrong at the server side. I have not changed anything in the code where I am subscribing for CloudKit events and handling push notifications - anyway also the version where it was working is not getting update notifications any longer. The application I am working on is published, thus changing container is no go. Not sure if this might be causing the issue, just want to mention: the app is using the same container for storing the Core Data in the cloud - the goal of the app upgrade is to migrate data to the CloudKit and use it as the cloud storage exclusively. It is confusing that everything was working fine for weeks and suddenly stopped working without any clear reason, probably as the effect of the load by intensive testing, adding record types...
Test with app developed from scratch:
I have written a simple test app to check receiving notifications. I can receive only the notification on record creation. What is wrong with my code:
import UIKit
import CloudKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
let container = CKContainer.defaultContainer()
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
let settings = UIUserNotificationSettings(forTypes: .Alert, categories: nil)
application.registerUserNotificationSettings(settings)
application.registerForRemoteNotifications()
return true
}
func application(application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: NSError) {
println("didFailToRegisterForRemoteNotificationsWithError: \(error)")
}
func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
println("didRegisterForRemoteNotificationsWithDeviceToken: \(deviceToken)")
subscribe()
}
func subscribe() {
// let predicate = NSPredicate(format: "text != %#", argumentArray: [""])
// let predicate = NSPredicate(format: "TRUEPREDICATE", argumentArray: nil)
let predicate = NSPredicate(value: true)
let subscription = CKSubscription(recordType: "Note", predicate: predicate, options: .FiresOnRecordDeletion | .FiresOnRecordUpdate | .FiresOnRecordCreation)
let notificationInfo = CKNotificationInfo()
notificationInfo.alertBody = ""
subscription.notificationInfo = notificationInfo
let publicDatabase = container.publicCloudDatabase
println("subscribing with CloudKit...")
publicDatabase.saveSubscription(subscription, completionHandler: { (returnedSubscription, error) -> Void in
if let error = error {
println("subscription error \(error.localizedDescription)")
} else {
println("subscription ok")
}
})
}
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
let ckNotification = CKQueryNotification(fromRemoteNotificationDictionary: userInfo)
println("didReceiveRemoteNotification: \(ckNotification)")
}
func applicationWillResignActive(application: UIApplication) {}
func applicationDidEnterBackground(application: UIApplication) {}
func applicationWillEnterForeground(application: UIApplication) {}
func applicationDidBecomeActive(application: UIApplication) {}
func applicationWillTerminate(application: UIApplication) {}
}
I have experienced this behavior in the past. In my case I could solve it by just deleting the subscription and creating it again. You should do that from code and not the dashboard. Doing it from the dashboard only works for the account that you are loged in into the dashboard.