是否有人在 WatchKit 中看到对 handleActionWithIdentifier:forLocalNotification: 的重复调用?

Is anybody else seeing duplicate calls to handleActionWithIdentifier:forLocalNotification: in WatchKit?

我的 WatchKit 处理本地通知操作时出现一些非常奇怪的行为,我很确定这是一个系统错误。我想知道是否有body其他人看到了同样的东西。

(这是使用 iOS 8.4 和 WatchKit 1.0,Objective-C 应用程序使用 Xcode 6.4 构建)

post的代码太多了,而且代码是客户端的属性,所以我得描述一下。

背景:

我正在为客户的应用程序添加自定义 "long look" 通知支持。

该应用程序在供应商位置周围创建了地理围栏。当用户进入其中一个地理围栏时,位置管理器会向处理地理围栏的我的 class 发送一条 didEnterRegion 消息。

我转身并生成定义类别的本地通知。该类别被定义为附加了 2 个不同的 UIMutableUserNotificationAction,一个用于显示有关供应商的更多信息,一个用于显示前往该供应商位置的行车路线。 (我们不会谈论当地理围栏触发时用户在供应商的喊叫距离内的事实,因此他们可以看到供应商的商店。这就是客户想要的,他付钱让我这样做。)

本地通知设置为立即触发(或者为了测试,我创建通知设置为在几秒钟内触发。)

通知触发时,系统可以执行以下 3 项操作之一。

1. If the app is running in the foreground, it will send the app delegate a `application:didReceiveLocalNotification:` message.
2. If phone is awake but the app is in the background, it displays the local notification with a system banner/alert (depending on the user's settings.) That banner/alert has buttons for my 2 actions.
3. If the phone is locked and the user has a paired Apple Watch that is allowed to receive notifications, the local notification is sent to the watch.

Apple Watch 应用程序有一个 WKUserNotificationInterfaceController 的自定义子 class,它被设置为处理此类用户通知。它向自定义界面控制器添加图像、标题和消息 body,并从附加到本地通知的 userInfo 字典中获取数据。

如果用户点击 WKUserNotificationInterfaceController 上的操作按钮之一("more info" 或 "directions"),手表的主界面控制器会收到一条 handleActionWithIdentifier:forLocalNotification: 消息。代码设置为随后向 iPhone 应用发送“openParentApplication:reply:error:”消息。它传递在本地通知中收到的用户信息字典。

iPhone 应用程序通过从位置管理器(启动地图应用程序)请求行车路线或从应用程序显示指定供应商的适当信息页面来响应 openParentApplication:reply:error 消息.

如果手表向 iPhone 发送 `openParentApplication:reply:error: 消息时 phone 被锁定,用户不会得到任何反馈,因为 phone 被锁定,Apple 不允许 phone 自行唤醒。

在这种情况下,我因此调用带有字典条目 @{@inBackGround: @(YES)} 的回复块。手表的回复块检查 inBackground==YES,如果是,它会向用户显示一条消息,他们需要打开 iPhone 应用程序才能看到 info/directions.

问题:

如果我启动 iPhone 应用程序并在 phone 第一次锁定时触发本地通知,消息会发送到手表,手表会显示我的自定义长外观 "more info" 和 "directions" 按钮,然后按其中一个操作按钮调用手表的 handleActionWithIdentifier:forLocalNotification: 方法,正如预期的那样。手表的 handleActionWithIdentifier:forLocalNotification: 方法向 phone 发送 openParentApplication:reply:error 消息,当用户返回应用程序时 phone 向用户显示适当的响应。

但是,如果我随后为具有不同 GPS 坐标和userInfo 指向要显示在 phone 上的不同屏幕信息。当我的手表发出嗡嗡声并且我将它举到手腕上时,随着显示新本地通知的 "long look" 通知,手表的 handleActionWithIdentifier:forLocalNotification: 方法再次触发,标识符和 userInfo 字典来自之前的本地通知。 (我没有在这个新通知上点击任何操作按钮,也没有在 phone 上回复本地通知消息。)

然后,如果用户点击手表新的长看通知控制器上的 "more info" 操作按钮,那个 操作会触发。

这样做的结果是,当用户转到他的 phone 时,他会看到他询问的新供应商的信息,但是当他点击该信息时,会出现该信息的副本对于他屏幕上的第一个供应商。

我对此进行了非常仔细的调试,并确认手表应用程序的界面控制器的 handleActionWithIdentifier:forLocalNotification: 方法被虚假调用。我在 iPhone posts 的本地通知中向 userInfo 添加了一个唯一的 NSDate 时间戳,我看到在第一次 [= 的第二次(虚假)调用中重复了完全相同的时间戳=15=]当显示第二个长看通知时。

有任何body其他运行解决这个问题吗?我想是时候提交 Radar 错误了,但我不确定我客户的应用程序中的哪一组步骤会触发问题,我可能需要一整天或更长时间才能制作出一个最小的演示应用程序来演示该问题。我从经验中知道请注意,Apple 不会 任何 关注我的错误报告,除非我给他们一个可以让他们创建可重复 fail-case 的应用程序,以及关于如何使用的痛苦详细说明它。

修复:

我想出的修复是一个可怕的黑客攻击。在 phone 上,我将唯一的 "actionFireDate" NSDate 嵌入到本地通知的 userInfo 字典中。在手表上,我在启动时创建了一个空的 NSMutableSet "actionFireDates"。当我接到一个 handleActionWithIdentifier:forLocalNotification: 电话时,我得到了本地通知的 userInfo,得到了我放入 userInfo 字典中的时间戳 NSDate,然后检查我的唯一 NSDate 是否存在"actionFireDates"设置。如果是,我就直接忽略这个动作。如果不是,我将 userInfo 字典中的新 NSDate 添加到我的动作触发日期集。

我很确定这是一个系统错误,并且已经在 Apple 的错误报告网站上打开了一个错误(A.K.A。提交了一个“雷达错误”。)

我想出的修复方法是将代码添加到我的自定义 WKInterfaceController class 的 awakeWithContext 方法中,该方法调用 dispatch_after 调用 dismissController 10 秒显示警报后。如果用户什么都不做,警报会自行消失。

我不会在几天内接受我的回答,以防其他人有关于这个主题的见解可以分享。

编辑:

A​​pple 关闭了我的 Radar 错误作为副本。我认为这意味着这确实是一个系统错误。