CloudKit推送通知didReceiveRemoteNotification从未调用过

时间:2015-07-12 16:29:33

标签: ios objective-c macos apple-push-notifications cloudkit

我正在使用CloudKit来存储用户数据,并希望在更改记录或创建新记录时获得推送通知。但它不起作用......

注册订阅,如下所示:

- (void) updateCloudSubscriptions {

    NSPredicate *allPredicate = [NSPredicate predicateWithFormat:@"TRUEPREDICATE"];
    CKSubscription *newOrUpdateSubscription = [[CKSubscription alloc]
        initWithRecordType:kMyRecordType predicate:allPredicate options:
        (CKSubscriptionOptionsFiresOnRecordCreation | CKSubscriptionOptionsFiresOnRecordUpdate)];
    CKNotificationInfo *newOrUpdateNotificationInfo = [CKNotificationInfo new];
    newOrUpdateNotificationInfo.shouldBadge = NO;
    newOrUpdateNotificationInfo.shouldSendContentAvailable = YES;
    newOrUpdateSubscription.notificationInfo = newOrUpdateNotificationInfo;

    CKDatabase *publicDatabase = [[CKContainer containerWithIdentifier:kMyContainerID] 
        publicCloudDatabase];
    [publicDatabase saveSubscription:newOrUpdateSubscription 
         completionHandler:^(CKSubscription *theSubscription, NSError *saveError) {
        if (saveError){
            //error handling
        }
        NSLog(@"Subscription created");
    }];
}

这成功了。在CloudKit仪表板上,订阅已正确创建

在我的 AppDelegate 中,我现在有以下内容:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    UIUserNotificationSettings *notificationSettings = [UIUserNotificationSettings settingsForTypes:
        (UIUserNotificationTypeNone | UIUserNotificationTypeAlert |
        UIUserNotificationTypeBadge | UIUserNotificationTypeSound) categories:nil];
    [application registerUserNotificationSettings:notificationSettings];
    [application registerForRemoteNotifications];
}

实现了这些委托方法:

- (void)application:(UIApplication *)application
    didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    NSLog(@"%@ with token = %@", NSStringFromSelector(_cmd), deviceToken);
}


- (void)application:(UIApplication *)application
    didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
    NSLog(@"%@ with error = %@", NSStringFromSelector(_cmd), error);
}


- (void)application:(UIApplication *)application 
    didReceiveRemoteNotification:(NSDictionary *)userInfo {
    NSLog(@"%@", NSStringFromSelector(_cmd));
}
使用令牌成功调用

didRegisterForRemoteNotificationsWithDeviceToken。但didReceiveRemoteNotification永远不会被调用。

我通过更改我的应用程序的Mac版本和iPhone版本上的值来测试这一点。两者都上传更改但都不会触发通知。我还尝试直接在仪表板上更改值,但这也不会导致通知。

我在这里缺少什么?

如果相关:我使用的是XCode 6.4的OS X 10.10

我已激活apsd日志记录,但只收到这样的消息:

Jul 12 18:25:29 Mac.local apsd[44748]: APSMessageStore - Saving database.
Jul 12 18:25:29 Mac.local apsd[44748]: APSMessageStore - Destroying database.
Jul 12 18:25:29 Mac.local apsd[44748]: APSMessageStore - Closed database.
Jul 12 18:25:29 Mac.local apsd[44748]: APSMessageStore - Reopening database
Jul 12 18:25:29 Mac.local apsd[44748]: APSMessageStore - Initializing database on thread: <NSThread: 0x7f8f1bf80dd0>{number = 55, name = (null)}
Jul 12 18:25:29 Mac.local apsd[44748]: APSMessageStore - Enabling auto vacuum.
Jul 12 18:25:29 Mac.local apsd[44748]: APSMessageStore - Enabling WAL journal mode.
Jul 12 18:25:29 Mac.local apsd[44748]: APSMessageStore - Enabling Foreign Key support.

2 个答案:

答案 0 :(得分:12)

2015 WWDC CloudKit Tips & Tricks video指出,如果要发送静默推送通知,则需要在notificationInfo字典上将shouldSendContentAvailable设置为true,如下所示:

let notificationInfo = CKNotificationInfo()
notificationInfo.shouldSendContentAvailable = true
subscription.notificationInfo = notificationInfo

答案 1 :(得分:6)

您的通知注册对于iOS 8是正确的,但在OS X上,您必须使用registerForRemoteNotificationTypes: NSApplication方法,而在iOS 7上使用registerForRemoteNotificationTypes: UIApplication方法。 Documentation

  

应用必须向Apple推送通知服务(APN)注册   接收应用推送提供商发送的远程通知。在iOS 8中   注册后有四个阶段:

     
      
  1. 注册您的应用支持使用的通知类型   registerUserNotificationSettings :.
  2.   
  3. 注册接收推送   通过调用您的应用程序通过APN发送通知   registerForRemoteNotifications方法。
  4.   
  5. 存储返回的设备令牌   成功注册到服务器的app委托,或   妥善处理注册失败。
  6.   
  7. 转发设备令牌   应用程序的推送提供商。
  8.         

    (在iOS 7中,而不是前两个步骤,   您通过调用registerForRemoteNotificationTypes:方法注册   UIApplication,在OS X中通过调用   registerForRemoteNotificationTypes:NSApplication的方法。)

同时实施didReceiveRemoteNotification:fetchCompletionHandler:而不是didReceiveRemoteNotification

  

使用此方法处理应用的传入远程通知。   与应用程序不同:didReceiveRemoteNotification:方法,即   只有当您的应用程序在前台即系统中运行时才会调用   当您的应用在前台运行或运行时调用此方法   背景。此外,如果您启用了远程通知   在后台模式下,系统启动你的应用程序(或从中唤醒它)   暂停状态)并将其置于远程时的后台状态   通知到了。但是,系统不会自动进行   如果用户强行退出,请启动您的应用。在那种情况下,   用户必须重新启动应用程序或在系统之前重新启动设备   尝试再次自动启动您的应用。

如果您希望通知唤醒您的应用,请务必编辑Info.plist并检查&#34;启用背景模式&#34;和#34;远程通知&#34;复选框:

enter image description here

由于您需要一个无声通知,根据文档,您应该只发送&#34; content-available&#34;标志为1,这样才对。但是还有其他用户在使用静音通知方面存在问题,显然,发送&#34;声音&#34;属性作为空字符串确实有帮助(see this question),因此您可以尝试将CKNotificationInfo.soundName设置为空字符串。