在iOS 11

时间:2017-06-28 07:51:27

标签: ios push-notification ios11

我注意到在iOS 11 beta 2上,无论应用的状态如何(背景/前景),静默通知都不会传递给application:didReceiveRemoteNotification:fetchCompletionHandler

我实施了UIApplicationDelegete方法application:didReceiveRemoteNotification:fetchCompletionHandler,然后发送以下静默推送

{  
  "aps": {  
    "content-available": 1  
  },  
  "mydata": {  
    "foo": "bar"  
  }  
} 

但是在iOS 11上没有调用委托方法。

它在其他版本的iOS上运行良好,文档部分Configuring a Silent Notification没有提到应该做的任何事情。

这是iOS 11中的错误还是我错过了iOS 11中的新功能?

请注意,我没有谈论或使用UserNotification框架,而这种框架不需要发送静默推送。

这是一个sample project,用于说明问题(您必须设置自己的捆绑ID)

当您在示例项目中进行午餐并将上述有效负载发送到应用程序时,您可以使用macOS控制台查看推送是否已正确传送到设备,而不是应用程序。

更新10.08

似乎行为是随机的。有时在重新启动设备后,有效负载会正确传送,但一段时间后它会停止工作。

正如您在下面的屏幕截图中看到的那样,标记为1的推送仅对设备进行了延迟,并且推送2(设备重启后)也会传送到应用程序。

enter image description here

更新14.08 - iOS 11 Beta 6

仍然是相同的行为。应该起作用的另一件事但不是以下。当应用程序的方案设置为"等待可执行文件启动"时,静音推送应该唤醒应用程序并在后台启动它。

enter image description here

更新21.08 - iOS 11 Beta 7

仍然是相同的行为,而不是来自Apple的错误报告中的更新。

更新29.08 - iOS 11 Beta 8

仍然是同样的问题。我现在使用的重现步骤如下:

  • 在Xcode项目方案中,选择"等待可执行文件启动"
  • didReceiveRemoteNotification: fetchCompletionHandler
  • 中添加断点
  • 在设备上启动应用
  • 发送上述无声推送

预期:应用从暂停状态进入后台并调用didReceiveRemoteNotification: fetchCompletionHandler

实际:没有任何反应

更新06.09 - iOS 11 Beta 10

我仍然有同样的马车行为。来自Apple的门票更新了以下答案:

  

Apple Developer Relations 2017年9月6日,下午10:42工程有   提供了有关此问题的以下反馈:

     

我们能够运行示例应用并测试行为。我们   当我们按照描述进行测试时没有发现任何问题。

     

推送并不能保证在应用程序运行时到达应用程序   背景,这里的日志表明我们不相信应用程序   被足够用来发动它。

     

我们确实看到我们在有条件时不时提供推动   好。

     

我们相信这是正确的行为。

更新11.09

我的Apple错误报告已关闭,并标记为33278611的副本仍然打开

更新13.09 - iOS 11 GM

感谢kam800的评论(见下文),我做了更多测试,并提出了这些意见:

在iOS 11 dasd DuetActivitySchedulerDaemon中似乎有一个新的守护进程要么完全丢弃数据推送,要么延迟数据推送:

交付推迟

控制台日志

default 13:11:47.177547 +0200   dasd    DuetActivitySchedulerDaemon CANCELED: com.apple.pushLaunch.net.tequilaapps.daylight:C03A65 <private>!   lifecycle   com.apple.duetactivityscheduler
default 13:11:47.178186 +0200   dasd    DuetActivitySchedulerDaemon Removing a launch request for application <private> by activity <private>   default com.apple.duetactivityscheduler
default 12:49:04.426256 +0200   dasd    DuetActivitySchedulerDaemon Advancing start date for <private> by 6.5 minutes to Wed Sep 13 12:55:31 2017   default com.apple.duetactivityscheduler
default 13:21:40.593012 +0200   dasd    DuetActivitySchedulerDaemon Activity <private>: Optimal Score 0.6144 at <private> (Valid Until: <private>)  scoring com.apple.duetactivityscheduler
default 13:21:40.594528 +0200   dasd    DuetActivitySchedulerDaemon Setting timer (isWaking=1, activityRequiresWaking=0) between <private> and <private> for <private>  default com.apple.duetactivityscheduler

推迟发送问题

  • 当推送数据推送并启动应用程序时,仅在达到交付日期时才会传递数据推送,该日期可能几分钟。这完全违背了使用数据推送来保持新应用程序的内容为下次发布做好准备的目的。我再次引用Apple的文档:
  

&#34;无声通知可帮助您保持用户体验   你的应用程序是最新的,即使它没有运行。&#34;

  • 两次数据推送发送到暂停的应用时,它们会被iOS 11推迟,而不是直接唤醒应用。达到交货时间后,仅交付最后一次数据推送!之前的推送丢失,并且未通过委托方法传递,导致数据丢失。

交货已取消

控制台日志

default 13:35:05.347078 +0200   dasd    DuetActivitySchedulerDaemon com.apple.pushLaunch.net.tequilaapps.daylight:C03A65:[
    {name: ApplicationPolicy, policyWeight: 50.000, response: {Decision: Must Not Proceed, Score: 0.00}}
 ], FinalDecision: Must Not Proceed}    scoring com.apple.duetactivityscheduler

取消投放问题

在这种情况下,数据推送完全丢失,并且在iOS 11上正确传送时从未在iOS 11上传送。

更新19.09 - iOS 11 GM

我还注意到,当应用程序位于前台并且通知未发送到应用程序时,我在控制台中看到以下日志:

default 08:28:49.354824 +0200   apsd    apsd    <private>: Received message for enabled topic '<private>' onInterface: NonCellular with payload '<private>' with priority 10 for device token: NO   courier-oversized   com.apple.apsd

fault   08:33:18.128209 +0200   dasd    Foundation  <NSXPCConnection: 0x151eee460> connection from pid 55: Exception caught during decoding of received message, dropping incoming message.
Exception: Exception while decoding argument 0 (#2 of invocation):
Exception: value for key 'NS.objects' was of unexpected class 'NSNull'. Allowed classes are '{(
    NSArray,
    NSData,
    NSString,
    NSNumber,
    NSDictionary,
    NSUUID,
    _DASActivity,
    NSSet,
    _DASFileProtection,
    NSDate,
    NWParameters,
    NWEndpoint
)}'.    general com.apple.foundation.xpc

13 个答案:

答案 0 :(得分:29)

因此iOS 11.1 beta 1的发行说明

  

iOS 11.1 beta 1刚刚发布,他们提到:   &#34;通知   已解决的问题   •更频繁地处理无声推送通知。 (33278611)

我做了一些测试,似乎确实已经修好了:

暂停状态

当我以暂停模式启动应用程序并发送静音推送时,应用程序将返回后台并调用didReceiveRemoteNotification:fetchCompletionHandler代理。

前景状态

以同样的方式,当应用程序在前台并发送静默推送时,代理似乎按预期调用。这是在之前的iOS 11版本中随机,所以我会在经过更多测试后确认这一点。

答案 1 :(得分:16)

我想在这里加上我的2美分,因为我也受到了这个问题的影响而且我已经注意到苹果公司在这个问题上关闭了几个雷达表示他们无法复制。我发现一个有趣的事情是,如果应用程序在连接到调试器的情况下处于后台运行状态,则会推送推送。

如果我杀了调试器,请拔掉我的手机,启动应用程序,然后发送静音推送有效负载,我看到应用程序没有被唤醒。我确实在控制台日志中看到系统取消了将负载传送到我的应用程序。

我已经提交了一个带有小样本应用程序的雷达,可以重现问题。我还在雷达中明确指出,在我的机票上工作的人不得运行连接到调试器的应用程序来重现问题。这是链接:https://bugreport.apple.com/web/?problemID=34461063

希望这会在这个问题上取得一些进展。

答案 2 :(得分:11)

看起来像iOS 11的新行为.iOS 11 beta 10提供了有关此问题的一些描述性日志:

default 23:18:51.806011 +0200   dasd    com.apple.pushLaunch.com.acme.Acme:F7E7D0:[
    {name: ApplicationPolicy, policyWeight: 50.000, response: {Decision: Can Proceed, Score: 0.50}}
    {name: BatteryLevelPolicy, policyWeight: 1.000, response: {Decision: Can Proceed, Score: 0.87, Rationale: [{batteryLevel == 62}]}}
    {name: DeviceActivityPolicy, policyWeight: 5.000, response: {Decision: Can Proceed, Score: 0.20}}
 ] sumScores:52.279483, denominator:81.410000, FinalDecision: Can Proceed FinalScore: 0.642175}
default 23:18:51.806386 +0200   dasd    'com.apple.pushLaunch.com.acme.Acme:F7E7D0' has compatibility score of 1.000000 with 'com.apple.CFNetwork-cc-111-79:E7272D'. Relaxing scores.
default 23:18:51.806855 +0200   dasd    'com.apple.pushLaunch.com.acme.Acme:F7E7D0' CurrentScore: 0.642175, ThresholdScore: 0.738454 DecisionToRun:0

看起来每个静音推送都会传送到iOS,但是dasd守护程序使用几个策略来决定是否应该向应用程序传送静音推送(例如电池电量)。昨天晚上我设法接受了一次静音推送,但当时我的iPhone已连接到充电器 - 可能是BatteryLevelPolicy得分高到足以接受一次无声推送。

Apple没有提供有关此iOS端行为的官方信息,只提供有关服务器端限制的信息:

  

无声通知并不意味着让您的应用程序保持清醒状态   背景,也不是高优先级更新。的APN   将无声通知视为低优先级,并可能限制它们   如果总数过多,则完全交付。实际上   限制是动态的,可以根据条件改变,但尽量不要   每小时发送一次以上的通知。

我保持手指交叉他们改变了这种行为,因为这会修复我的应用程序:)另一方面,这种改变很好 - 许多事情之一使iPhone电池持续时间比Android手机更长。

答案 3 :(得分:7)

iOS 11.1测试版发行说明包括: 通知 已解决的问题 更频繁地处理静默推送通知。 (33278611)

答案 4 :(得分:6)

Apple Developer Relations刚刚在我的雷达上添加了评论:

  

我们认为此问题已在最新的iOS 11.2测试版中得到解决。

     

请使用最新的iOS测试版进行测试。如果您还有问题,请   使用任何相关日志或信息更新您的错误报告   可以帮助我们调查。

     

https://developer.apple.com/download/

目前正在安装iOS 11.2测试版 - 将测试静默推送行为

答案 5 :(得分:5)

iOS 11.1 Beta 2还包含

Notifications
Resolved Issues
• Silent push notifications are processed more frequently. (33278611)
发行说明中的​​

- 现在将对其进行测试。

更新 - 11.10.2017 - iOS 11.1 Beta 2

在“真实场景”中使用我们的应用程序2天后,看起来这个版本的iOS有了真正的改进。我小心翼翼地开始相信这是固定的。

答案 6 :(得分:3)

iOS 11.4.1,Swift 4

我遇到了(来自CloudKit的)静默推送未到达的问题,我尝试了所有人在这里提到的所有内容。然后,我决定尝试为这样的alertBody对象设置一个空白的CKNotificationInfo()

let info = CKNotificationInfo()
info.shouldSendContentAvailable = true
info.alertBody = ""

这使推送的发送优先级更高(但它们仍然是静默推送),而且我的设备日志中再也没有错误消息,忽略了该推送。

我希望能对某人有所帮助。 :)

答案 7 :(得分:2)

我的应用程序遇到了类似的问题,直到iOS 10我才收到推送通知并且application:didReceiveRemoteNotification:fetchCompletionHandler被正确调用。但是当更新到iOS 11时,推送通知停止工作。

我的代码问题是,即使我在推送通知有效负载中使用content-available:1和mutable-content:1,也没有启用后台提取选项。但它在iOS 10之前完美运行。

Make sure you turned ON both these capabilities.

将背景提取功能设置为ON后,它正在运行

答案 8 :(得分:2)

作为一种解决方法我们正在添加“通知”键并在“标题”中添加空字符串作为值。 这会唤醒appDelegate中的didReceive回调。

答案 9 :(得分:1)

所以这确实是iOS 11中的一个错误,它现在已经在iOS 11 beta 3中得到修复。现在,当在前台或后台都收到静音推送时,application:didReceiveRemoteNotification:fetchCompletionHandler被正确调用。 / p>

<强>更新

不,它没有修复,并且仍在iOS beta 3和4中发生

答案 10 :(得分:1)

在撰写此答案时,我正面临与Bill Dunay's答案完全相同的问题。

我的要求是当应用程序处于前台状态时接收静默通知,而当应用程序在后台/未运行时则不接收任何通知。我的解决方法是这样。我不使用徽章,因此将其设置为零对我来说不是问题。

{
    "aps" : {
        "badge" : 0,
        "sound" : ""
    },
    "mydata": {  
        "foo": "bar"  
    }  
}

请注意,我故意不使用“可用内容”。导致iOS优化逻辑开始延迟/取消通知传递的设置。

答案 11 :(得分:0)

在我的情况下,在服务器站点上完成工作后,使用了静默通知来更新ui,因此在应用程序中包含不相关的内容很麻烦。因为我们用于静默通知的有效负载甚至包含标题和正文,所以我实现了这些方法以在活动/不活动的应用程序中获取工作通知,而不是充电并且关闭了后台应用程序刷新,甚至处于低功耗状态。

要使其正常工作,我添加了委托并使用UNUserNotificationCenterDelegate协议和willPresent notification(iOS 10+)方法创建扩展,每次使用正确的有效负载触发该扩展。要在应用处于活动状态时不显示通知,只需用徽章或声音呼叫完成即可。 我最终得到了这样的东西

    import UserNotifications

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?

    // MARK: - Lifecycle
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        UNUserNotificationCenter.current().delegate = self
        return true
    }

    //this was only method to handle notifications before
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any],
                     fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        //process silent notification
        completionHandler(UIBackgroundFetchResult.newData)
    }
}

extension AppDelegate : UNUserNotificationCenterDelegate {
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        //proces notification when app is active with `notification.request.content.userInfo`
        if UIApplication.shared.applicationState == .active {
            completionHandler(.badge)
        }else {
            completionHandler(.alert)
        }
    }
}

要在应用处于后台运行且无提示通知时使这些状态工作,请不要调用我的方法,我会通过以下方式直接从applicationDidBecomeActive的通知中心获取通知:

UNUserNotificationCenter.current().getDeliveredNotifications { (notifications) in
            debugLog(message: "unprocessed notification count: \(notifications.count)")
            if notifications.count > 0 {
                notifications.forEach({ (notification) in
                    DispatchQueue.main.async {
                        //handle `notification.request.content.userInfo`
                    }
                })
            }
        }

答案 12 :(得分:0)

就我而言,iPhone设置中的“后台应用刷新”已关闭。因此,推送通知已发送到设备,但未发送到应用程序。启用后台应用程序刷新会在应用程序中收到静默推送。

这可能不是此问题的实际答案,以防万一有人需要检查。