I have a WKInterfaceLabel
on my WatchKit App storyboard. Every 30 seconds, the WatchKit App will send a request to the parent iPhone app to get a string. Upon receiving the string, I set the string as the WKInterfaceLabel
's text. Code looks like this:
NSDictionary *getTokenRequest = @{@"request":@"getToken"};
[InterfaceController openParentApplication:getTokenRequest reply:^(NSDictionary *replyInfo, NSError *error) {
if (error) {
NSLog(@"%@", error);
} else {
token = replyInfo[@"token"];
NSLog(@"token=%@", token); // I am getting the correct token
// But the following line doesn't update label text
[self refreshToken];
}
}];
- (void)refreshToken {
if ([token length] != 0) {
[self.codeLabel setText:token];
}
}
When app launches or resumes, the label will display the correct string returned from parent app. This is due to calling refreshToken
in willActivate
. What's not working is when I request data from the parent app every 30 seconds, I am also calling refreshToken
in the callback of the request as shown in the code above, even though I am getting the correct string (token
here) from the phone app and calling [self.codeLabel setText:token]
. It's the same method call: when called within willActivate
, setText
updates the label fine, but when called in the callback method of a request, the label text UI doesn't update.
This issue happens only on device. When running on simulator, the label text updates every 30 seconds as expected.
When I was developing an iPhone app, I once had a similar issue, and it was resolved by calling the setText
method on the main thread:
[self performSelectorOnMainThread:@selector(refreshToken) withObject:nil waitUntilDone:NO];
Sadly, the same fix does not work for Apple Watch.
I have also found a similar thread here: can setText for WKInterfaceLabel in init method but not in didselectrow method however it does not provide a good solution.
Any suggestions/thoughts are appreciated. Thanks in advance!
In the end, this is what worked for me:
Thanks to this post http://iosdevelopmentjournal.com/blog/2013/01/16/forcing-things-to-run-on-the-main-thread/.
In short, when UI is not updating when you tell it to, it might not be scheduled to run on the main thread.
As shown in my question, I have already suspected the threading issue and tried to use
performSelectorOnMainThread
but it didn't work. For those curious, here's the difference betweenperformSelectorOnMainThread
anddispatch_async
: Whats the difference between performSelectorOnMainThread and dispatch_async on main queue?