2015-07-12 57 views
9

我正在使用CloudKit存儲用戶數據,並希望在更改記錄或創建新記錄時獲取推送通知。但它不工作...CloudKit推送通知didReceiveRemoteNotification永不會調用

註冊訂閱這樣的:

- (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 Dashboard上,訂閱已正確創建

在我的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版本上的值,測試了此操作。都上傳更改,但都不會觸發通知。我也嘗試直接在儀表板上更改這些值,但也沒有導致通知。

我在這裏錯過了什麼?

如果相關:我在OS X 10.10用了XCode 6.4

我激活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. 
+0

當前存在更新通知的CloudKit錯誤。你有沒有嘗試添加新記錄的應用程序?有關更新錯誤的更多信息,請參閱https://forums.developer.apple.com/thread/7288 –

+0

@EdwinVermeer,這很有趣。但是,我也沒有收到創建記錄的通知。 – codingFriend1

+0

在目標應用程序功能中,您有遠程通知的背景模式嗎? –

回答

6

您的通知註冊對於iOS 8是正確的,但是在OS X上,您必須使用registerForRemoteNotificationTypes:方法NSApplication和iOS 7上的registerForRemoteNotificationTypes:方法UIApplicationDocumentation

的應用程序必須使用蘋果推送通知服務(APN的),以 登記接收由應用的推送提供商發送遠程通知。在iOS中8 後來,註冊有四個階段:

  1. 註冊您的應用程序支持使用 registerUserNotificationSettings的通知類型:。
  2. 通過呼叫您的應用程序的 registerForRemoteNotifications方法註冊接收推送 通知。
  3. 將設備令牌存儲返回 由服務器的應用程序代表成功註冊,或 妥善處理註冊失敗。
  4. 將設備令牌轉發給 該應用程序的推送提供程序。

(在iOS系統7,而不是前兩個步驟, 通過調用registerForRemoteNotificationTypes寄存器:方法的UIApplication的 ,和在OS X通過調用 registerForRemoteNotificationTypes:的NSApplication的方法)

還實現didReceiveRemoteNotification:fetchCompletionHandler:,而不是didReceiveRemoteNotification

使用此方法處理傳入的應用程序的遠程通知。 與應用程序不同的是:didReceiveRemoteNotification:方法,即 僅在您的應用程序在前臺運行時調用,系統 在您的應用程序在前臺運行或 後臺運行時調用此方法。另外,如果啓用了遠程通知 後臺模式,系統將啓動您的應用(或從 掛起狀態中喚醒),並在遠程通知到達時將其置於後臺狀態。但是,如果用戶強制退出,系統不會自動啓動您的應用程序 。在這種情況下, 用戶必須重新啓動您的應用或重新啓動設備,然後系統 嘗試再次自動啓動您的應用。

如果你想通知喚醒您的應用程序,請務必編輯Info.plist並勾選「啓用後臺模式」和「遠程通知」複選框:

enter image description here

既然你想有一個無聲的通知,每個文檔,你應該只發送「內容可用」標誌爲1,所以這是正確的。但還有其他用戶在使用靜默通知時遇到問題,顯然,將「sound」屬性作爲空字符串發送會有所幫助(see this question),因此您可以嘗試將CKNotificationInfo.soundName設置爲空字符串。

+0

感謝您的詳細解答,Baris。我確實在OS X上正確註冊;代碼剛剛沒有在我的問題中列出。我總是在iOS 8上進行測試,因此在那裏註冊應該是正確的。這些應用程序在測試時一直處於前景狀態,但我也添加了背景通知和'didReceiveRemoteNotification:fetchCompletionHandler:'但仍未調用。對我來說,這是非常神祕的... – codingFriend1

+1

@ codingFriend1看到我更新的答案:嘗試將CKNotificationInfo.soundName設置爲空字符串。也許它有幫助,它似乎已爲[其他](http://stackoverflow.com/questions/19239737/silent-push-notification-in-ios-7-does-notwork)... –

+0

是的!那是失蹤的拼圖。 'soundName'必須設置爲了接收通知。 對不起,我花了這麼長時間來驗證這一點,你只收到了一半的賞金。無論如何:非常感謝您的幫助! – codingFriend1

10

2015 WWDC CloudKit Tips & Tricks video指出,如果要發送一個無聲推送通知,您需要在您的notificationInfo字典中設置shouldSendContentAvailable爲true,如下所示:

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

謝謝,但添加國旗並沒有影響... – codingFriend1

+0

這是不可用的TVOS,以防萬一你想知道... – user3069232

+0

非常感謝你這!當我的應用程序在後臺運行超過4個小時後,我一直在努力避免被調用的方法。 – ShayanK