好吧,我不建议您使用与手表本身的网络操作相关的任何内容。首先,因为显而易见的原因,苹果不建议这样做。直接在手表上执行的唯一网络操作是加载图像。
我一直在与网络操作作斗争,观察了大约一周并得出结论,目前最稳定的方法并不明显。
主要问题是WKInterfaceController.openParentApplication(...)
不按预期工作。人们不能只是请求打开 iPhone 应用程序并按原样返回响应。有大量的解决方案指出在中创建后台线程- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void (^)(NSDictionary *))reply
本来可以很好地工作,但实际上却不然。问题是这个方法必须发送reply(...);
马上。即使创建同步请求也无济于事,您将不断收到“错误 -2 iPhone 应用程序未回复..”,大约是 10 次的 5 倍。
所以,我的解决方案如下:
您实施:
func requestUserToken() {
WKInterfaceController.openParentApplication(["request" : "token"], reply: responseParser)
}
并解析响应以查找如果 iPhone 没有响应可能会发生的错误。
iOS 端
- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void (^)(NSDictionary *))reply
{
__block UIBackgroundTaskIdentifier watchKitHandler;
watchKitHandler = [[UIApplication sharedApplication] beginBackgroundTaskWithName:@"backgroundTask"
expirationHandler:^{
watchKitHandler = UIBackgroundTaskInvalid;
}];
NSString *request = userInfo[@"request"];
if ([request isEqualToString:@"token"])
{
reply(@{@"token" : @"OK"});
[PSWatchNetworkOperations.shared loginUser];
}
dispatch_after( dispatch_time( DISPATCH_TIME_NOW, (int64_t)NSEC_PER_SEC * 1 ), dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 ), ^{
[[UIApplication sharedApplication] endBackgroundTask:watchKitHandler];
} );
}
这段代码只是创建一个后台线程,强制 iPhone 发送网络请求。假设您的 iPhone 应用程序中有一个特殊的类,它会发送这些请求并发送要观看的答案。目前,这只能通过使用来完成应用程序组 https://developer.apple.com/library/prerelease/ios/documentation/Miscellaneous/Reference/EntitlementKeyReference/Chapters/EnablingAppSandbox.html#//apple_ref/doc/uid/TP40011195-CH4-SW19。因此,您必须为您的应用程序和 watchkit 扩展创建一个应用程序组。之后,我建议使用毫米波虫洞 https://github.com/mutualmobile/MMWormhole为了在您的应用程序和扩展程序之间建立通信。该手册非常不言自明。
现在这一切还有什么意义呢?您必须实现向服务器发送请求并通过虫洞发送响应。我使用 ReactiveCocoa,所以我的代码示例如下:
- (void)fetchShoppingLists
{
RACSignal *signal = [PSHTTPClient.sharedAPIClient rac_GET:@"list/my" parameters:@{@"limit":@20, @"offset":@0} resultClass:PSShoppingListsModel.class];
[signal subscribeNext:^(PSShoppingListsModel* shoppingLists) {
[self.wormHole passMessageObject:shoppingLists identifier:@"shoppingLists"];
}];
[signal subscribeError:^(NSError *error) {
[self.wormHole passMessageObject:error identifier:@"error"];
}];
}
正如您在这里看到的,我发回响应对象或错误。请注意,您通过虫洞发送的所有内容都应该与 NSCoding 兼容。
现在在手表上您可能会像这样解析响应:
override func awakeWithContext(context: AnyObject?) {
super.awakeWithContext(context)
PSWatchOperations.sharedInstance.requestUserToken()
PSWatchOperations.sharedInstance.wormhole.listenForMessageWithIdentifier("token", listener: { (messageObject) -> Void in
// parse message object here
}
})
}
所以,得出结论。您向父应用程序发送请求以从后台唤醒并启动异步操作。立即发回reply()。当您收到操作的答复时,请发送您已收到答复的通知。同时聆听您的 watchExtension 中的响应。
抱歉,文字太多了,但我只是希望它能帮助大家保持冷静,因为我为此花费了很多精力。