(228) WatchKit Tips & Tricks (Video)
These are the very important Tips and Tricks that we should know when develop Apple Watch apps:
- Networking: we want to do all the networking on Watch-Extension itself, not using the iPhone app (this approach will work on both OS1 and OS2), so use dispatch_semaphore to keep the background task alive!
- Reach iPhone app: openParentApplication(reply:) won’t be on OS2. On OS2 we will be using WatchConnectivity. There are 4 different modes how to communicate with the counterpart app, we can send messages, files between apps (files will be waiting for iPhone app and delivered when the iPhone app launch later) check out: https://developer.apple.com/library/prerelease/watchos/documentation/General/Conceptual/AppleWatch2TransitionGuide/UpdatetheAppCode.html#//apple_ref/doc/uid/TP40015234-CH6-SW1
- Use app Groups to share data, NSUserDefault should be used for state data only.
- Handoff – lots of things can, and should be left to the iPhone to perform, so use updateUserActivity(userInfo:webpageURL:) to update
- UI loading: definitely load visible elements first, then show immediately, then load things that users have to scroll to see. (Also, if something changes don’t reload everything).
- Interface Builder: Images should be properly sized. Use setImageData() instead of setImage(), so we can choose encryption (PNG/JPG ..)
- Assets: use assets, the 2X asset will be a fallback to be used if LARGER WATCHES come out in the future.
- Animated: reduce size and FPS (frame per second) … no need to have a high FPS, a lower one should suffice (24?). U
- Animation API on OS2: similar to UIView animation, we will be able to animate height, width, alpha, content insets … Lots of cool stuffs.
- Take user directly to voice dictation is possible
- Notifications: use body & title (for short look) of the alert key. Category key can actually specify which Interface Controller to be used for Long look. Static Notification is to be used in Notification Center, so do not neglect it.
- Glances: ensure always have content ! System-provided snapshot will be removed from UI when willActivate finishes, so do full-setup before willActivate finishes. Use absolute time instead of “10 minutes ago” as the “10 minutes ago” may not be updated info.
(?) Reloading Glance :
“As a user is swiping between Glances, well, ‘will activate’ is going to get called on yours, and so if they swipe past yours and in ‘will activate’ you’re loading a whole bunch of stuff, doing some processing, doing a network request, well, that’s probably not the most efficient you could be doing that.
So make sure that you are reloading very deliberately, depending on other circumstances and not just, ‘hey, they looked at my content.’ The other thing, as in with Watch apps, is to limit the number of alternate layouts.”
(?) Glance “disappear” issue:
“You’re loading in the content, everything’s going great, and then, oh, where did content go, and then boom, it slams in when it updates.” WHY?
“So what happens is that system-provided snapshot is going to be removed from the UI when ‘will activate’ finishes. So a little contrary to what you do within the Watch app itself, here you want to make sure that you are doing your full setup before ‘willActivate’ finishes.”
You want to get all the information you need, set it so that the UI is up and ready to go so that when we remove that snapshot, it’s right there. There’s no in-between state of the whole screen disappearing.
The other thing that you should do is reload the content deliberately.
(?) Glance “interaction”:
As Apple Glance for Music can use Digital Crown to change the volume -> can we use the Crown to interact with the Glance?
(?) Glance “Application Context”:
The piece of data that should be shown on Glance – should be put in Application Context which is sent from the iOS app ! (http://asciiwwdc.com/2015/sessions/713)
(?) Long-running data-fetching on Watch
“When fetching data from your Watch app, remember that your app can be deactivated at any time. If you use a default session for your request, your app might exit before it receives any data. To prevent your app from exiting immediately, you can use the
performExpiringActivityWithReason:usingBlock: method of
NSProcessInfo to extend your app’s life for a short time.”
WK Interface Controller (Link)
The main cornerstone of WatchKit is this InterfaceController. It’s main functions, attributes and especially navigation-based stuffs are the must-know for developers !
- Use init & awakeWithContext: to initialise variables, load data, … For all InterfaceController except root-interface-controller -> need to save the context object passed. (Root has nil).
- willActivate should not initialise, only update the changed values.
- didDeactivate – any attempt to change UI is not working if the controller not active. This function is used to clean up. (Simulator: Use hardware ->lock to test deactivation).
- (Time consumption of init?) – How app architecture affects the initialisation of interface-controllers? From my understanding, the Page-based will initialise all pages first, but the hierarchy only initialise the first level? Or do all controllers in Storyboard got initialised?
pushControllerWithName:context: to push new controller (WatchKit will perform animation). The Context object is the only way to tell the new controller what to display.
- If we use SEGUEs -> use
contextForSegueWithIdentifier: - to specify the context object to pass on to the controller.
- Standard Input Interfaces:
- Alert & Action sheets: presentAlertControllerWithTitle:message:preferredStyle:actions:
- Text Input: presentTextInputControllerWithSuggestions:allowedInputMode:completion:
- Video & audio playback: presentMediaPlayerControllerWithURL:options:completion:
- Audio Recording: presentAudioRecordingControllerWithOutputURL:preset:maximumDuration:actionTitle:completion:
- Passkit Passes:
- IsInitialController //Root
- HidesWhenLoading //Hide content until after willActivate
- Background //Bg image
- Mode //Mode for bg image
- Animate //Animate bg image immediately
- Color // Bg color
- Subclassing: you want to subclass WKInterfaceController so to add your own properties to it – then later you can change the content. If Controller is to present Local/Push Notifications -> use WKNotificationInterfaceController
- init & awakeWithContext: //Init
- willActivate & didDeactivate //Activation events
pushControllerWithName:context:, popController, popToRootController //Navigation
presentControllerWithName:context:, presentControllerWithNames:contexts:, presentAlertControllerWithTitle:message:preferredStyle:actions:, dismissController //Modal
+reloadRootControllersWithNames:contexts:, becomeCurrentPage //Page-based
presentTextInputControllerWithSuggestions:allowedInputMode:completion:,dismissTextInputController //Text Input
- table:didSelectRowAtIndex: //Table Selection