I’m starting to get into iOS development using Xamarin.
So to start out, I followed the Quick Start tutorials for Xamarin Forms but as a twist decided to also do it using F#. I didn’t just figure out how to do it in F# however, I used the following resources to help out:
- Writing Xamarin.Forms apps in F# by Charles Petzold
- Combining F# And Xamarin Forms To Create Mobile Applications by Jonathan Wood at Wintellect
- F# sample project from Wintellect - Github to go with the above link.
You can find my implementations of the Quick Start on github at:
Xamarin Forms Quick Start in C# and F# on GitHub
Though I want to draw attention to one part of the project which was a puzzle for me given my current knowledge (or lack thereof) of F#.
Async Event Handlers in F#
In the Quick Start tutorial the Call button click is an async event handler. So this (taken from MainPage.xaml.cs
):
async void OnCall(object sender, EventArgs e)
{
if (await DisplayAlert(
"Dial a Number",
"Would you like to call " + translatedNumber + "?",
"Yes",
"No"))
{
var dialer = DependencyService.Get<IDialer>();
if (dialer != null)
dialer.Dial(translatedNumber);
}
}
So its an async event handler in C#, but how on earth do you do this in F#?
As F# has similar but different ways of doing async (that came before C# async) we need to code it differently. So here is the equivalent in F# (taken from MainPage.fs
). Note that I’ve split it into two methods to make a bit clearer:
member this.makePhoneCall = async {
let! ok = Async.AwaitTask(this.DisplayAlert("Dial a Number", sprintf "Would you like to call %s ?" translatedNumber, "Yes", "No"))
if ok then
let dialer = DependencyService.Get<IDialer>()
if not(Object.ReferenceEquals(dialer, null))
then dialer.Dial(translatedNumber) |> ignore
}
member this.OnCall(sender : Object, e : EventArgs) =
this.makePhoneCall |> Async.StartImmediate
One of the key differences between C# and F# async is that in F# the async block (async { ... }
in makePhoneCall
) is a specification; it does not execute the code. You need to specifically start it using Async.StartImmediate
in OnCall
. This method starts the async block immediately on the current thread which in this case is the UI thread (which is needed as we’re interacting with the UI).
Some resources I found really helpful:
- Asynchronous C# and F# (I.): Simultaneous introduction from Tomas Petricek.
- Asynchronous Workflows (F#) on MSDN
- Tip #1 in the Six Essential Tips for Async on Channel9 - Discussion on
async void
. But all the tips are really good if you need to brush up on async in C#.