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 个已完成的单元。
我结束了:
- 正在删除手表上的应用和 iPhone
- 重新启动两者
- 正在重新安装
而且有效。
我已经为 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 个已完成的单元。
我结束了:
- 正在删除手表上的应用和 iPhone
- 重新启动两者
- 正在重新安装
而且有效。