Redesign OnPlatform

StephaneDelcroixStephaneDelcroix USInsider, Beta ✭✭✭✭
edited December 2016 in Xamarin.Forms Evolution

Summary

The current OnPlaform implementation is not easily extendable if we don’t want it to become an API mess.
Also, it is impossible for a 3rd party Platform creator to implement and use OnPlatform without having our approval.

Important things to care about

  • We do not want to break API or ABI usage
  • TargetPlatform is used in Device.OnPlatfom(), in OnPlatform<T>, in xmlns definition

Proposed change (first try): Fun with Flags

  • Deprecate Device.OnPlatform(). Our users are smart enough to write switch statement in code.
  • Change the TargetPlatform enum to be a [Flags]. That will allow one to write a statement for multiple platforms. We will achieve ABI stability by reserving the 3 first bits of the enum for legacy usage, and API stability by keeping the same names:
    [Flags]
    public enum TargetPlatform
    {
        // 3 first bits reserved for legacy use
        iOS = 1<<3,
        Android = 1<<4,
        WinPhone = 1<<5,
        Windows = 1<<6,

        // 24 first bits reserved for future usage
        // use any number from 1<24 to 1<30 for your own platform

        Other = 1<<31,
    }
  • change the OnPlatform<T> xaml utility class so it supports the following syntax. The legacy properties will stay, but will be deprecated
<OnPlatform x:TypeArguments=“x:String”>
    <On Platform=“iOS”>iOS</On>
    <On Platform=“Android|Windows”>androidOrWindows</On>
    <On Platform=“0x1000000”>myAwesomePlatform</On>
</OnPlatform>
  • change both Xaml parser so they support enum values as ints, hexes or binary literals (c# 7, I’m ready) with or without _ as digit separator
  • change whatever is required to XamlNativeView keeps working

Warning

Compiled code using if (Device.OS == TargetPlatform.iOS) won’t work anymore. Setting Device.OS to 1<<1 | iOS won’t fix it, because of the ==

Discussion (with self)

I can’t say how much I love this technical hack, and the fact that it uses [Flags], but the slight regression is a no go, as it’ll be a nightmare to debug.

Proposed Change (second try): Magic Strings

  • Deprecate TargetPlatform and Device.OnPlatform (after reverting the Tizen addition). Suggest our users to use a switch statement on RuntimePlatform instead
  • Add a new string property to Device: something like RuntimePlatform
  • Add string consts for known platforms
  • in OnPlatform<T>, deprecate properties, allow this syntax:
<OnPlatform x:TypeArguments=“x:String”>
    <On Platform=“iOS”>iOS</On>
    <On Platform=“Android>android</On>
    <On Platform=“3rdPartyPlat”>myAwesomePlatform</On>
</OnPlatform>
  • change whatever is required to XamlNativeView keeps working

We might want to make sure xaml intellisense suggest the right names for the Platform property, to avoid typos.

Backward Compatibility Story

  • when setting RuntimePlatform to any known value, we will set Device.OS to the correct TagetPlatform value, and use TargetPlatform.Other in any other case.
6
6 votes

Completed · Last Updated

https://github.com/xamarin/Xamarin.Forms/pull/658 was merged

Posts

  • TheRealJasonSmithTheRealJasonSmith USXamarin Team Xamurai

    Method 2 seems the most sane.

  • AdamPAdamP AUUniversity ✭✭✭✭✭

    As another option for the Flags idea. Since WinPhone is only used by Windows Silverlight, which is deprecated and Windows 8.1 RT and UWP are both using Windows. Why not just drop WinPhone.

    Then we have
    iOS = 1,
    Android = 2,
    Windows = 4

    Which means we could use flags.

    Since I think I might have been only 1 of very few people to ever use XF with Windows SL and WinRT. Even I don't use those platforms anymore, that should be saying something :)

  • TheRealJasonSmithTheRealJasonSmith USXamarin Team Xamurai

    The problem with moving to a flags enum is that we cant enable external parties to play nice with it. :/

  • ChaseFlorellChaseFlorell CAInsider, University mod

    I like the idea of using the enum but as an Enumeration Class whereby the class can be extended beyond the capabilities of an enum, however... I'm not sure how it would work with [Flag]s.

    https://lostechies.com/jimmybogard/2008/08/12/enumeration-classes/

  • StephaneDelcroixStephaneDelcroix USInsider, Beta ✭✭✭✭

    We will go with strings. We can have the benefits of the [Flags] quite easily, both in code as the switch statement allows multiple case

    switch (platform) {
    case "iOS":
    case "Android":
        return "iOS or android";
        break;
    }
    

    and in Xaml, as we could make the language support

    <OnPlatform x:TypeArguments=“x:String”>
        <On Platform=“iOS,Android”>iOS or Android</On>
        <On Platform=“3rdPartyPlat”>myAwesomePlatform</On>
    </OnPlatform>
    
  • TheRealJasonSmithTheRealJasonSmith USXamarin Team Xamurai

    +1 for second try outlined in OP with modifications as specified by Stephane

This discussion has been closed.