Reputation: 489
I have currently a problem. My wanted behaviour: If I open my WatchKit App, I call "openParentApplication". I receive my wanted data. But if I tested on real devices, it doesnt work since I open the parent app in the iPhone. But when I'm testing in simulator it works without to open the parent app.
My Xcode Version is 6.3.2 and iOS 8.3.
What could be the problem?
InterfaceController.m
- (void)awakeWithContext:(id)context {
[super awakeWithContext:context];
NSDictionary *userInfo = @{@"request":@"refreshData"};
[WKInterfaceController openParentApplication:userInfo reply:^(NSDictionary *replyInfo, NSError *error)
{
entries = replyInfo;
NSLog(@"Reply: %@",replyInfo);
[self reloadTable];
[self.city setText:[entries valueForKey:@"city"][0] ];
}];
}
AppDelegate.m
- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void(^)(NSDictionary *replyInfo))reply
{
NSString *refresh = [userInfo valueForKey:@"request"];
if([refresh isEqualToString:@"refreshData"])
{
NSString *city = [[NSUserDefaults standardUserDefaults] stringForKey:@"City"];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:[NSString stringWithFormat:@"http://blackdriver.adappter.de/api/retrieve.php?city=%@",[city stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]] parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject)
{
reply(responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
NSLog(@"Error: %@", error);
}];
}
}
EDIT - Correct answer: See the link from mohammed alwaili in the comments
Upvotes: 3
Views: 1633
Reputation: 41
I had a similar issue and had to work through a few problems to have my WatchKit app successfully call iOS app which made an asynchronous API call.
Here's a working code snippet
func application(application: UIApplication, handleWatchKitExtensionRequest userInfo: [NSObject : AnyObject]?, reply: (([NSObject : AnyObject]!) -> Void)!) {
let backgroundProcessingToken = application.beginBackgroundTaskWithName("backgroundApiCall", expirationHandler: { () -> Void in
reply(["response":["error":"SOME_ERROR_CODE_INDICATING_TIMEOUT"]])
})
request(.GET, "https://api.forecast.io/forecast/[INSERT DARK SKY API CODE]/37.8267,-122.423").responseJSON(options: NSJSONReadingOptions.AllowFragments, completionHandler:{request, response, data, error in
if(error != nil || data == nil){
reply(["response":["error":"SOME_ERROR_CODE_INDICATING_FAILURE"]])
}
if let json = data as? NSDictionary {
reply(["response":["data":json]])
}
application.endBackgroundTask(backgroundProcessingToken)
})
}
Ultimately, you need to register as a background task to ensure your app doesn't get killed by the operating system.
I also have a working example here on github FWIW
Upvotes: 2
Reputation: 2813
A openParentApplication:reply
request must return immediately, so you'll have to request extra time for your asynchronous
request to finish (alternately run a synchronous
request, but this is terrible practice).
From the Apple WatchKit Developer Tips and Best Practices:
If your app on Apple Watch needs to perform longer running background tasks, such as networking calls, you should rely on your iPhone app to do the work. Use the openParentApplication:reply: method in WKInterfaceController to wake up your iPhone app in the background and return the data that your WatchKit extension needs. The UIApplicationDelegate method that handles the WatchKit request must return immediately. If an asynchronous call is required, to perform networking for example, use a background task to make sure your app is not suspended before it has a chance to send its reply.
Upvotes: 3