iOS-WatchKit 文件传输工作不可靠

iOS-WatchKit File Transfers Work Unreliably

我已经为 iOS 9 和 WatchOS 2 构建了一个应用程序。iOS 应用程序会定期将图像文件从 iPhone 传输到手表。有时,这些是从应用程序推送的,有时是 Watch 请求(拉取)它们。如果拉取,我使请求异步,并在两种情况下使用完全相同的 iOS 代码来传输图像。

大约一半时间(可能是 2/3)文件传输有效。其他时候,似乎什么也没有发生。无论我是推还是拉图像,这都是一样的。

在 iOS 方面,我使用类似于此的代码(会话已激活):

   if ([WCSession isSupported]) {
      WCSession *session = [WCSession defaultSession];
      if (session.reachable) {
         NSData *imgData = UIImagePNGRepresentation(img);

         NSURL *tempFile = [[session watchDirectoryURL] URLByAppendingPathComponent: @"camera.png"];
         BOOL success = [imgData writeToFile: [tempFile path] atomically: NO];
         if (success) {
            NSLog(@"transferFile:metadata:");
            [session transferFile: tempFile metadata: nil];
         } else {
            NSLog(@"will not call transferFile:metadata:");
         }
      } else {
         NSLog(@"Camera watch client not reachable.");
      }
   }

在手表扩展方面,我有一个激活手表会话并接收文件的单例:

- (void)session:(WCSession *)session didReceiveFile:(WCSessionFile *)file {
   // pass the data file to the data listener (if any)
   [self.dataListener session: session didReceiveFile: file];
}

我的“数据侦听器”将文件转换为 UIImage 并将其显示在 UI 线程上。但是,这可能无关紧要,因为不成功的操作永远不会走到那一步。

在不成功的传输过程中,从不调用 session:didReceiveFile:。但是,如果我检查 iOS 应用程序的日志,我会看到这些消息 仅在失败的操作期间 :

Dec 26 15:10:47 hostname companionappd[74893]: (Note ) WatchKit: application (com.mycompany.MyApp.watchkitapp), install status: 2, message: application install success

Dec 26 15:10:47 hostname companionappd[74893]: (Note ) WatchKit: Purging com.mycompany.MyApp.watchkitapp from installation queue, 0 apps remaining

这里发生了什么?该应用似乎正在尝试重新安装 Watch 应用 (?)。发生这种情况时,我 没有 查看手表应用程序 crash/close 并重新启动。它什么都不做。没有收到文件。

在 iOS 方面,我将图像缩小到大约 136x170 像素,因此 PNG 文件不应太大。

知道出了什么问题吗?

更新:

我已经发布了一个完整的、最小的项目来演示这个问题on Github here

我现在的印象是这是模拟器中的错误。它似乎在 Apple Watch 硬件上更可靠地工作。不过不确定它是否 100% 可靠。

Apple 错误报告已提交 (#24023088)。如果有任何状态,将更新状态,并留下 未解决 任何可能提供解决方法的潜在答案。

这就是我如何设法将文件从 phone 传输到手表:
为了使其工作,该文件必须位于 appGroupFolder 中,并且必须从 Capabilities 选项卡中启用“App Groups”,因为 phone 并观看。

为了获取 appGroup 文件夹,请使用以下代码行:

NSURL * myFileLocationFolder = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier: @"myGroupID"]; //something like group.bundle.projName

一旦你得到它,就可以使用它来发送消息并处理来自手表的响应:

 [session sendMessage:@{@"file":myFileURL.absoluteString} replyHandler:^(NSDictionary<NSString *,id> * _Nonnull replyMessage) {
                //got reply
            } errorHandler:^(NSError * _Nonnull error) {
                //got Error
            }];

尽管 WCSession *session = [WCSession defaultSession]; 我注意到有时 session 会被释放,所以您可以考虑改用 [WCSession defaultSession];

要在 phone 上捕获它,请使用:

- (void)session:(WCSession *)session didReceiveMessage:(NSDictionary<NSString *, id> *)message replyHandler:(void(^)(NSDictionary<NSString *, id> *replyMessage))replyHandler{
 //message[@"file"] - addres to my file
 //do stuff with it here

 replyHandler(@{@"myResponse":@"responseData"}); //this call triggers replyHandler block on the watch
}

现在,如果您没有忘记实施 WCSessionDelegate 并使用

if ([WCSession isSupported]) {
    _session = [WCSession defaultSession];
    _session.delegate = self;
    [_session activateSession];
}
//here session is @property (strong, nonatomic) WCSession * session;

一切正常。

做了更广泛的回答,希望能接触到更多人。

对我来说,没有一个传输是有效的。轮询 transfer.progress 显示 isTransferring == true,但我从未超过 0 个已完成的单元。

我结束了:

  1. 正在删除手表上的应用和 iPhone
  2. 重新启动两者
  3. 正在重新安装

而且有效。