iOS / Apple Watch:iPhone 应用程序在后台时未触发应用程序网络请求回调块
iOS / Apple Watch: iPhone app network request callback blocks not triggered when app is in background
我的 Apple Watch 应用向配套 iPhone 应用发送消息。在主应用程序的 handleWatchKitExtensionRequest
中,我向服务器发送请求:
- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void (^)(NSDictionary *))reply {
if ([[userInfo objectForKey:@"request"] isEqualToString:@"getPendingChallenge"]) {
[MyClient getPendingNotifications:someId withDomain:host withSuccessBlock:^(id responseObject) {
// process responseObject
...
reply(response);
return;
} withFailureBlock:^(NSError *error, NSString *responseString) {
// error handling
return;
}];
}
}
getPendingNotifications
以上只是使用 AFNetworking 的常规网络 GET 请求。
应用程序处于活动状态时一切正常。因为此网络请求用于填充我的 Apple Watch 上的 UI,所以我不希望主应用处于活动状态。但是,当 iPhone 上的主应用程序处于后台时,我可以看到正在发送网络请求,但是上面代码中的 withSuccessBlock
或 withFailureBlock
回调块永远不会被触发。
phone 应用程序可以在后台模式下接收网络请求响应吗?如果是这样,我做错了什么?
尝试将请求作为同步请求发送。
我猜你的请求是异步请求(在正常情况下应该是这样)。在后台模式下,设备将在后台线程中启动您的应用程序,而您为请求创建了一个新线程。
我在网上找到了适合我的解决方案,post (http://www.fiveminutewatchkit.com/blog/2015/3/11/one-weird-trick-to-fix-openparentapplicationreply),作者是 Brian Gilham。
这是适合我的代码。
- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void (^)(NSDictionary *))reply {
// There is a chance that the iOS app gets killed if it's in the background
// before it has a chance to reply to Apple Watch.
// The solution is to have the app respond to the request asap, then complete other tasks.
// The following code begins – and ends, after two seconds – an empty background task right at the beginning of this delegate method
// Then we kick off a background task for the real work
// For more details see http://www.fiveminutewatchkit.com/blog/2015/3/11/one-weird-trick-to-fix-openparentapplicationreply
__block UIBackgroundTaskIdentifier bogusWorkaroundTask;
bogusWorkaroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[[UIApplication sharedApplication] endBackgroundTask:bogusWorkaroundTask];
}];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[[UIApplication sharedApplication] endBackgroundTask:bogusWorkaroundTask];
});
__block UIBackgroundTaskIdentifier realBackgroundTask;
realBackgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
reply(nil);
[[UIApplication sharedApplication] endBackgroundTask:realBackgroundTask];
}];
if ([[userInfo objectForKey:@"request"] isEqualToString:@"getPendingChallenge"]) {
[self handleWatchKitGetPendingChallengeRequest:reply];
}
[[UIApplication sharedApplication] endBackgroundTask:realBackgroundTask];
}
- (void)handleWatchKitGetPendingChallengeRequest:(void (^)(NSDictionary *))reply {
...
[MyClient getPendingNotifications:someId withDomain:host withSuccessBlock:^(id responseObject) {
// process responseObject
reply(response);
return;
} withFailureBlock:^(NSError *error, NSString *responseString) {
// error handling
reply(nil);
return;
}];
}
我的 Apple Watch 应用向配套 iPhone 应用发送消息。在主应用程序的 handleWatchKitExtensionRequest
中,我向服务器发送请求:
- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void (^)(NSDictionary *))reply {
if ([[userInfo objectForKey:@"request"] isEqualToString:@"getPendingChallenge"]) {
[MyClient getPendingNotifications:someId withDomain:host withSuccessBlock:^(id responseObject) {
// process responseObject
...
reply(response);
return;
} withFailureBlock:^(NSError *error, NSString *responseString) {
// error handling
return;
}];
}
}
getPendingNotifications
以上只是使用 AFNetworking 的常规网络 GET 请求。
应用程序处于活动状态时一切正常。因为此网络请求用于填充我的 Apple Watch 上的 UI,所以我不希望主应用处于活动状态。但是,当 iPhone 上的主应用程序处于后台时,我可以看到正在发送网络请求,但是上面代码中的 withSuccessBlock
或 withFailureBlock
回调块永远不会被触发。
phone 应用程序可以在后台模式下接收网络请求响应吗?如果是这样,我做错了什么?
尝试将请求作为同步请求发送。
我猜你的请求是异步请求(在正常情况下应该是这样)。在后台模式下,设备将在后台线程中启动您的应用程序,而您为请求创建了一个新线程。
我在网上找到了适合我的解决方案,post (http://www.fiveminutewatchkit.com/blog/2015/3/11/one-weird-trick-to-fix-openparentapplicationreply),作者是 Brian Gilham。
这是适合我的代码。
- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void (^)(NSDictionary *))reply {
// There is a chance that the iOS app gets killed if it's in the background
// before it has a chance to reply to Apple Watch.
// The solution is to have the app respond to the request asap, then complete other tasks.
// The following code begins – and ends, after two seconds – an empty background task right at the beginning of this delegate method
// Then we kick off a background task for the real work
// For more details see http://www.fiveminutewatchkit.com/blog/2015/3/11/one-weird-trick-to-fix-openparentapplicationreply
__block UIBackgroundTaskIdentifier bogusWorkaroundTask;
bogusWorkaroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[[UIApplication sharedApplication] endBackgroundTask:bogusWorkaroundTask];
}];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[[UIApplication sharedApplication] endBackgroundTask:bogusWorkaroundTask];
});
__block UIBackgroundTaskIdentifier realBackgroundTask;
realBackgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
reply(nil);
[[UIApplication sharedApplication] endBackgroundTask:realBackgroundTask];
}];
if ([[userInfo objectForKey:@"request"] isEqualToString:@"getPendingChallenge"]) {
[self handleWatchKitGetPendingChallengeRequest:reply];
}
[[UIApplication sharedApplication] endBackgroundTask:realBackgroundTask];
}
- (void)handleWatchKitGetPendingChallengeRequest:(void (^)(NSDictionary *))reply {
...
[MyClient getPendingNotifications:someId withDomain:host withSuccessBlock:^(id responseObject) {
// process responseObject
reply(response);
return;
} withFailureBlock:^(NSError *error, NSString *responseString) {
// error handling
reply(nil);
return;
}];
}