Gone Mobile: Episode 24: Cross-Platform Performance Comparisons with Kevin Ford

Ever wanted to know how different app frameworks and approaches compare with each other when it comes to performance? In this episode we spoke to Kevin Ford to dig into exactly that. Join us for a look at how the native SDKs, Xamarin, and Cordova compare for various performance measurements.

Hosts: Greg Shackles

Guest: Kevin Ford

Links:

Thanks to our Sponsors!

Raygun.io

Raygun.io – Exceptional Error Tracking
Raygun.io is the fastest and easiest way to track your application’s errors and get the level of detail you need to fix crashes quickly. Notifications are delivered right to your inbox and presented on a beautiful dashboard.

Johan Karlsson: Navigation from a ListView

The problem to be solved

One drawback with the vanilla ListView that comes with Xamarin.Forms is that once an item is selected it can’t be selected again until you select something else and reselect it. Usually this is fine, unless you use the ListView to navigate away to a new page. When you return you cannot re-navigate to the same page again.

The solution

The solution to this is simple, just hook up to the ItemSelected event for the ListView and set the SelectedItem property to null.

So the short version of you quick-googlers would be the following line of code. (in the View)

  // Reset the selected item to make it selectable again
  duckListView.ItemSelected += (s, e) => {
    duckListView.SelectedItem = null; 

And the navigation should be done in the ViewModel

        public Duck SelectedDuck
        {
            set 
            {
                if (value != null)
                {
                    // IoC omitted, we should really get someone else to 
                    // create these objects for us.
                    var viewModel = new DuckViewModel() { Duck = value };
                    var page = new DuckView(viewModel);
                    _navigation.PushAsync(page);
                }
            }
        }

The more verbose version

You could also navigate directly from this event handler, but you should feel it deep in your heart that that is just wrong. Instead we handle navigation in the ViewModel. I’ve created a sample project to do this. Also, I’m doing this without any additional framework that would handle navigation for you so that’s why I need to provide my ViewModel with a navigation interface.

I’ll present each file to you below or just download the sample solution from here.

The Model

Our model is simple. It’s just a duck with a name… As you might recall, a model could be anything really. In this case it’s a simple class.
    
    public class Duck
    {
        public string Name
        {
            get;
            set;
        }
    }

The ViewModel (s)

We’ve got two ViewModels, but it’s really only the MainViewModel that’s interesting. It initializes it’s own data, which usually should be done async from another source. It doesn’t implement INotifyPropertyChanged either, as is should but for this sample it’s good enough.

What to focus on is the SelectedDuck property that handles the navigation. We only implement a setter for this since we reset the selected item anyhow in the view itself and on top of that navigate away from the page.


    /// <summary>
    /// The sample ViewModel. Should implement INotifyPropertyChanged
    /// </summary>
    public class MainViewModel
    {
        private INavigation _navigation;

        public MainViewModel(INavigation navigation)
        {
            _navigation = navigation;

            Ducks = new List<Duck>()
            {
                new Duck() { Name = George },
                new Duck() { Name = Bob },
                new Duck() { Name = Sarah },
                new Duck() { Name = Clint },
            };
        }

        /// <summary>
        /// A list of ducks
        /// </summary>
        /// <value>The ducks.</value>
        public List<Duck> Ducks
        {
            get;
            set;
        }

        public Duck SelectedDuck
        {
            set 
            {
                if (value != null)
                {
                    // IoC omitted, we should really get someone else to 
                    // create these objects for us.
                    var viewModel = new DuckViewModel() { Duck = value };
                    var page = new DuckView(viewModel);
                    _navigation.PushAsync(page);
                }
            }
        }
    }

The other ViewModel (DuckViewModel) simply references the selected duck on the page we navigate to.

   public class DuckViewModel
    {
        public DuckViewModel()
        {
        }

        public Duck Duck
        {
            get;
            set;
        }
    }

The View

That leaves us with the view that consists of two parts; XAML and the code behind. Usually you don’t want any code expect the ViewModel-binding in the code-behind since it’s very platform coupled, but in this case we need to do an exception. We need to reset the SelectedItem property of the ListView.
    public partial class MainView : ContentPage
    {
        public MainView()
        {
            InitializeComponent();
            BindingContext = new MainViewModel(this.Navigation); // Should be injected

            // Reset the selected item to make it selectable again
            duckListView.ItemSelected += (s, e) => {
                duckListView.SelectedItem = null; 
            };
        }
    }


The XAML parts look like this.
xml version=1.0 encoding=UTF8?>
<ContentPage xmlns=http://xamarin.com/schemas/2014/forms xmlns:x=http://schemas.microsoft.com/winfx/2009/xaml x:Class=ListViewNavigation.MainView>
    <ContentPage.Content>

      <ListView x:Name=duckListView
             IsGroupingEnabled=false
             ItemsSource={Binding Ducks}
             HasUnevenRows=true
             SelectedItem={Binding SelectedDuck}>
    <ListView.ItemTemplate>
      <DataTemplate>
        <ViewCell>
            <Label Font=Large Text={Binding Name} />
        </ViewCell>
      </DataTemplate>
     </ListView.ItemTemplate>
    </ListView>

    </ContentPage.Content>
</ContentPage>

Summary

There is a lot missing in forms of Ioc and base frameworks for MVVM (like MvvmLight och MvvmCross). Is there an alternative for the extreme mvvm-purists? Yes, you could hook up a GestureRecognizer on each item in the ListView but some platform specific animations will be lost if you do so.

Please give feedback what ever you feel like! And if there’s a better way, I would love for you to enlighten me! 😀

Nic Wise: Authenticating with Touch ID and the iPhone pin

One thing I really love about the new iOS devices – iPhone 5S, 6, 6+ and the iPad Air 2 – is the Touch ID sensor. I’ve always had a PIN on my devices – there is too much important information on my phone to not have one – and TouchI ID takes the pain out of it1. It’s also core to the iOS experience: Apple Pay relies on it, and it’s used by iTunes and a lot of other Apple apps.

Touch ID promo shot

But one thing I want is a nice, easy way to use the Touch ID sensor in my own apps. iOS8 introduced the Local Authentication APIs. This makes it easy – trivial – to request a Touch ID authentication.

var context = new LAContext ();
context.EvaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, "Do Secret Stuff", (bool success, NSError error) => {
    if (success) {
        //yay
    } else {
        switch (error.Code) {
        case LAStatus.AuthenticationFailed:
            break;
        case LAStatus.UserCancel:
            break;
        //etc
        }
    }
});

This is all good and easy, but it gives the user an option I don’t like: they can use Touch ID, or they can enter a password (or cancel). And if there is no Touch ID, it’ll just not work – it’s finger prints or nothing. Worse, there is no way to turn off the password option (or change the text).

Touch ID shot using LAContext

One thing I didn’t know about until recently is that you can get the same – or similar – prompt, but allow it to fall back to the devices PIN, without a password option. This means it works on any iOS8 device.

For most of my uses – validate that the person on the phone is the owner or someone the owner has trusted – this is the best option.

It’s just not that obvious how to do it.

The general idea for this – and I’m assuming it’s a bit of a hack workaround – is to put a new item into the Keychain, but set it’s ACLs to require the user to authenticate in order to get it back. The magic ACLs are

new SecAccessControl (SecAccessible.WhenPasscodeSetThisDeviceOnly, SecAccessControlCreateFlags.UserPresence)

In Objective-C land, this is kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly and kSecAccessControlUserPresence. For the life of me, I can’t find reference to it in Apple’s docs, but they do have a sample and also slides from a WWDC session on this. Maybe we get the docs in iOS9.

The full call to create the Keychain item is this:

var secret = NSData.FromString (UIDevice.CurrentDevice.IdentifierForVendor.ToString(), NSStringEncoding.Unicode);

var record = new SecRecord (SecKind.GenericPassword) {
    Service = NSBundle.MainBundle.BundleIdentifier,
    Account = "SecurityViewAccount",
    AccessControl = new SecAccessControl (SecAccessible.WhenPasscodeSetThisDeviceOnly, SecAccessControlCreateFlags.UserPresence),
    UseNoAuthenticationUI = true,
    ValueData = secret
};

var res = SecKeyChain.Add (record);

return (res == SecStatusCode.Success);

You can update it in a similar manner if needed, as the add will fail if the item already exists. To do the actual authentication:

var query = new SecRecord (SecKind.GenericPassword) {
    Service = NSBundle.MainBundle.BundleIdentifier,
    Account = "SecurityViewAccount",
    AccessControl = new SecAccessControl (SecAccessible.WhenPasscodeSetThisDeviceOnly, SecAccessControlCreateFlags.UserPresence),
    UseOperationPrompt = "Your message goes here", 
};
SecStatusCode status;

var res = SecKeyChain.QueryAsData (query, false, out status);
if (res != null) {
    return NSString.FromData(res, NSStringEncoding.Unicode).ToString ();
}

return null;

A non-null result means they authenticated – if you need it, the result is the secret that you stored when you created the item. This shows a subtley different UI to the user:

Touch ID UI with PIN

And better yet, on iOS8 devices without Touch ID, the user is prompted for the PIN if they press “Enter Passcode”.

There is still no customisation of the dialog. No option to ONLY use Touch ID (no PIN), which would be nice. And no fallback for devices which have no PIN set at all – you’d need to make your own PIN screen for that.

I’ve put together a very basic project which shows how it works. It’s iOS8 only, tho it works on iOS7 – it just will not let you in! When I get around to rewriting Trip Wallet, I think I’ll use this as the main authentication method.


  1. The only thing I don’t like is, sometimes, when I want to hit the media controls, the phone has already logged me in. First world problem, I know. ?