• WatchKit 2.0 realities

    As expected, Apple unveiled the latest additions to WatchKit and just as unexpectedly I pretty much nailed it. Here are some links to resources for the new stuff mixed with some first impressions…

    The biggest change is that native watchOS apps are now possible. Essentially, watch extensions now just runs on the device. Easy-peasy. This change alone should result in much better watch apps, by removing the round-trip involved in every interface update.

    Apple’s update guide provides instructions for getting watchOS 1 apps running as a native watch app.

    Applications will have access a healthy handful of system frameworks. Access to HealthKit and CoreMotion APIs should be a boon to fitness app and game developers.

    The newly introduced components which can be used in 3rd party apps are…

    • WKInterfacePicker – A control which can display a sequence of images and it controlled by the digital crown. In face, this seems to be the only way to get digital crown access. In practice this might be kinda lame as it’s bound to the UI paradigm of a picker.
    • WKInterfaceMovie – A control which when tapped plays a full screen movie. Movies don’t play inline and require a push. Not awesome.

    Additionally, there are new modal alert and microphone recording controls available from WKInterfaceController.

    WKExtensionDelegate is a new protocol which handles all the lifecycle based events that the root interface controller was forced to deal with before. This is a very welcome addition.

    XPC between watchOS apps and iOS apps are handled by the new Watch Connectivity Framework. It’s nice to see that the concept of file transfer is a first class citizen here. Transferring NSData in a userInfo dictionary always felt hacky.

    As I’d hoped, NSURLReqest operations are seamlessly filtered back to the iPhone, even in native watchOS code…

    WatchKit extensions can access the network directly using an NSURLSession object. WatchKit extensions have full access to the NSURLSession capabilities, including the ability to download files in the background.

    Third party developers can now provide watch face complications. The familiar complications types are supported. Generic “image” complications provide hooks (via CLKImageProvider) for doing custom rendering.

    Haptic feedback can be initiated through the WKDevice playHaptic: method. It takes an WKHapticType. Audio playback via the WKAudio... classes seems pretty robust, expect there is no Core Audio for advanced processing. Sorry Marco :(

  • A flock of curly braces

    Swift Braces

    Going deep with optional checking in Swift.

  • WatchKit 2.0 expectations

    Apple operations executive Jeff Williams pre-announced enhancements to the Apple Watch SDK which open the door for native third party apps. Williams specifically mentioned sensor access for health apps and games, but there are lots of unanswered questions about what will be available to developers. I have some thoughts.

    My first and biggest assumption is that WatchKit interface elements aren’t going away. Sure, there will be enhancements, new components, and capabilities1, but I wouldn’t expect UIKit2 to magically start running on the Watch. My expectation is a stripped down version WKInterfaceController (let’s call it WKNativeInterfaceController) is introduced (a big if), which link against Foundation, WatchKit, and some other choice frameworks. As Marco mentioned, those other frameworks will determine a lot of capabilities for native apps, especially with respect to media presentation. But in general, I expect most UIs will still be made up of WKInterfaceButton/Image/Group/Whatever. This change alone would result in much snappier watch apps, as they don’t have to round trip back to the phone for every interface update. The level of custom control rendering is big question. But assuming some options there, apps could process any locally available information and update it’s interface without involving the phone at all. Slow bluetooth/wifi communication is invoked only when needed. Networking requests could invisibly proxy through the phone and in general the watch app will be able to call back to the main app when a long running task needs to be performed. It’s XPC all the way down.

    Williams also mentioned Digital Crown access in the upcoming SDK. I’d expect this to take the form of a new callback on WKNativeInterfaceController which provides a stream of changes since the last rotation (or something similar). This combined with custom control rendering would allow for editable dials and would be suitable for controlling games.

    Sensor access introduces some interesting issues. The accelerometer isn’t used in any current first party apps as a input mechanism (e.g. there is no shake to undo). I’d be surprised to see Apple open this up to third party developers without using it themselves. My guess is that they’ll open up limited access to HealthKit (to read relevant data such as heart rate and calories burned) and the microphone (think recording voice notes). I’d love to see Apple offer some form of gesture recognizers for the touch screen. Custom tapping and panning handling would open up a lot of possibilities.

    Apps will likely be given some amount of storage which is managed by the phone app. This could be used to sync offline music. Likely this performs similar to the current image caching mechanisms (with higher storage allotments per app).

    I do expect watch apps to be able to take advantage of any new HomeKit APIs by directly communicating with devices even when not connected to a phone. iBeacon support would be nice as well.

    I don’t think it will be possible to create iOS caliber interfaces in the new WatchKit, but I do expect to be able to build snappier watch apps which can be run when an iPhone isn’t in range. That alone is a damn good year over year update.

    1. I’m personally hoping for a full frame Glance template.

    2. Some current WatchKit classes reference things like UIColor and UIImage which are part of UIKit. Linking against these becomes problematic without providing access to all of UIKit. They could make a third parallel class set to cover these (e.g WKColor to go along with UIColor and NSColor), but they should unify this and bring these common concepts down into Foundation.

  • CJ Cregg Is Not A News Anchor

    Lord knows I love The West Wing, but one thing that never made sense is CJ’s frequent roll as news anchor broadcasting from the White House press room.

    In the season four episode 20 Hours in America, she breaks news about a pipe bombing at a swim meet. She then proceeds to answer press corps questions about the event while listening in on first responder updates through an ear piece. The script thankfully spares us any of their questions for an event which they learned of just 5 seconds ago. None of this makes any sense and feels like a very forced way of providing exposition and giving CJ something to do in the episode.

    And just so this post isn’t all CJ bashing, here she is saying butter 14 times in about 45 seconds.

  • An approach to reusable WatchKit interface components

    In the course of developing a WatchKit app, seasoned developers will quickly grow tired of the limitations imposed by the lack of reusable interface components.

    In iOS (and other MVC frameworks), this problem is addressed through the use of view controllers. In well-architeched applications, view controllers are used everywhere, even for the smallest bits of interface. View controllers act like building blocks, allowing larger, more complex interfaces to be composed of multiple view controllers. The end result can result in a codebase that feels a bit like building an app with LEGO. Sophisticated interfaces can be created by snapping together existing components. The only “new” code a developer has to write are the pieces that are different from every other interface in the app, and then these pieces are available to be snapped into future interfaces.

    WatchKit, as it stands today, lacks a direct equivalent to this approach. WKInterfaceController serves this purpose for entire screens, but the reliance on Interface Builder to instantiate interface elements doesn’t allow the kind modular composition that makes UIViewController so powerful on iOS.

    As an example, consider an avatar button. In a hypothetical social media application, it’s highly likely that multiple screens in a Watch app will display a circular avatar. This means adding a WKInterfaceButton to each WKInterfaceController, easy enough. However, the avatar images are remote, so there is some networking and cache checking code that needs to happen before the image on the button can be set. Also, WKInterfaceButton lacks a corner radius function, so all images must by clipped into a circle before being sent to the watch. This means that a few somewhat fiddly function calls must be made everywhere an avatar button is shown, and if anything in the design or implementation changes, it needs to be updated everywhere. This is an error prone approach to interface development. The net result being worse WatchKit applications.

    A solution I’ve arrived at in my own experience developing in WatchKit is something I’ve labeled interface components. These are simple classes (the root InterfaceComponent class is directly descended from NSObject) which manage the coordination of model objects and WKInterfaceObject instances. They are instantiated in WKInterfaceController and other InterfaceComponent instances, the latter allowing for the creation of rich, reusable interface components composed of multiple, smaller components.

    Following the earlier example, the API for an AvatarComponent might look something like:

    @interface SIGAvatarComponent : NSObject
    - (void)setupWithPerson:(ModelPerson *)person interfaceImage:(WKInterfaceImage *)interfaceImage;
    @end
    

    All logic of downloading and preparing the avatar can then be abstracted away inside of the component.

    - (void)setupWithPerson:(ModelPerson *)person interfaceImage:(WKInterfaceImage *)interfaceImage
    {
    	// Assume a model class extension for preparing images.
    	[person roundedAvatarImage:^(UIImage *image, NSError *error) {
    	    NSData* imageData = UIImagePNGRepresentation(image);
    	    [interfaceButton setBackgroundImageData:imageData];
    	}];
    }
    

    For any view that needs to display an avatar, it’s a simple matter of wiring up a WKInterfaceImage in IB, instantiating an AvatarComponent and passing in the correct objects. If a change a change needs to be made (e.g. design now calls for square avatars), every avatar in the entire WatchKit app (including Glance and notifications views) can be updated from a single place.

    Taking this a step further, one could make a PostComponent which take a post object, a WKInterfaceGroup which displays a photo and a nested WKInterfaceButton meant to be a floating avatar. PostComponent can handle displaying the main photo, but delegate the avatar setup to it’s own instance of AvatarComponent by providing it with post.author and the WKInterfaceButton:

    - (void)setupWithPost:(ModelPost *)post backgroundGroup:(WKInterfaceGroup *)backgroundGroup avatarImage:(WKInterfaceImage *)avatarImage
    {    
    	//Delegate setup of avatar to AvatarComponent
    	[self.avatarComponent bindInterfaceImage:self.avatarImage withPerson:post.author];
    	
    	// Again, assume a model class extension for preparing images.
    	[post posterImage:^(UIImage *image, NSError *error) {
    		[self.backgroundGroup setBackgroundImageData:UIImagePNGRepresentation(image)];
    	}];
    }
    

    While this approach does require duplication on the Interface Builder side, as each WKInterfaceController will need to replicate the WKInterfaceObject heirarchy, it does allow for the development of modular, resuable interface elements which can dramatically reduce the amount of duplicated code in WKInterfaceController subclasses.

    Additional notes...

    A small nicety is to add a deactivate method to a root InterfaceComponent class, and then message all component instances from WKInterfaceController's didDeactivate method. This provides a hook to do any teardown operations required by components.

    Additionaly, InterfaceComponent instances are suitable to use as row controllers in WKInterfaceTable. A custom subclass can be made which adds table specific properties such as row number.

  • The perfect suggested text algorithm

    Predictive Text: See you there, neat!, fuck you

    Honestly, I don't know why they even make this configurable.