Programming WatchKit with F#
Disclaimer: This is just a hack. I’m not in any position to make announcements about stuff, but Xamarin loves F# and I’m sure that better solutions than this are forthcoming. But this was fun to get running, so…
Xamarin just released it’s Preview of Watch Kit support and naturally, I had to see if it was possible to use F# to program the forthcoming Apple Watch. Yes, it is.
As always with Watch Kit Apps, the Xamarin solution consists of three projects:
- A Parent app that is a normal iOS app;
- An Extension that runs on a connected iPhone and executes the program logic; and
- A Watch App that runs on the Watch and is essentially a remote display for the Extension App
You can read much more about this at Xamarin’s Watch Kit Documentation site.
To create an F# Watch solution, first create an F#-based Parent App. Then, add the Extension project to that app, an F#-based Custom Keyboard Extension. Finally, add a Watch App from the C#/iOS/Unified/Apple Watch solution template.
The Watch App consists only of a storyboard and resources. It doesn’t actually have any C# (or F#) code in it.
Follow these instructions to [set project references and identifiers].
Switching the Extension from Custom Keyboard to Watch Kit
You will have to manually edit the
info.plist of the Watch Extension:
NSExtension, switch the
NSExtensionAttributes, add a
WKAppBundleIdentifierkey to the identifier of your Watch App (e.g.,
Now you can get rid of the template F# code and replace it with something like this:
type InterfaceController(ip : IntPtr) =
override this.Awake (context) =
this.myLabel.SetText("F# |> I ♡")
Again, this is covered in much more detail in Xamarin’s docs, but every scene in the Watch App’s storyboard is backed by a subtype of
WKInterfaceController. Since it’s loaded from a Storyboard, it uses the constructor that takes an
Awake method is called when the controller is instantiated.
The Hacky Part
Xamarin has not yet released designer support for Watch Kit, so for now, you need to edit your Watch App’s Storyboard in XCode Interface Builder.
That’s not the hacky part.
Once you’ve designed your UI, you have to hand-edit the Storyboard XML, adding
connections elements that define your outlets (properties) and actions (event-handlers). You have to set the
destination attribute to refer to the
id of the associated control:
But really, that’s the only ugly part! ;-)
Back in your Extension app, you now have to use attributes to link up your F# code with elements within the Storyboard. The
RegisterAttribute on your
WKInterfaceController links to the
customClass attribute of the
controller element, and the name of your
OutletAttribute properties must correspond to the
property attribute of the
outlet elements. Finally, the
selector attribute of your
action elements must have a corresponding
open System open UIKit open Foundation open WatchKit [<register ("InterfaceController")>] type InterfaceController(ip : IntPtr) = inherit WKInterfaceController(ip) let mutable label : WKInterfaceLabel = null let mutable button : WKInterfaceButton = null let mutable clickCount = 0 [<outlet>] member this.myLabel with get() = label member this.myLabel with set(v) = label < - v [<Outlet>] member this.myButton with get() = button member this.myButton with set(v) = button < - v [<Action("OnButtonPress")>] member this.OnButtonPush () = clickCount < - clickCount + 1 sprintf "Pressed %d times" clickCount |> this.myLabel.SetText override this.Awake (context) = System.Console.WriteLine("Hello F#") this.myLabel.SetText("F# |> I ♡")
And that’s really all there is to putting F# on your wrist!
[video width="1644" height="1172" mp4="/uploads/2015/01/WatchKitF.mp4"][/video]