Напишите специфичный для платформы устройства код в Xamarin.Формы

#c# #xamarin.ios #xamarin #xamarin.android #xamarin.forms

#c# #xamarin.ios #xamarin #xamarin.android #xamarin.forms

Вопрос:

У меня следующая Xamarin.Forms.ContentPage структура классов

 public class MyPage : ContentPage
{
    public MyPage()
    {
        //do work to initialize MyPage 
    }

    public void LogIn(object sender, EventArgs eventArgs)
    {
        bool isAuthenticated = false;
        string accessToken = string.Empty;

        //do work to use authentication API to validate users

        if(isAuthenticated)
        {
            //I would to write device specific code to write to the access token to the device
            //Example of saving the access token to iOS device
            NSUserDefaults.StandardUserDefaults.SetString(accessToken, "AccessToken");

            //Example of saving the access token to Android device
            var prefs = Application.Context.GetSharedPreferences("MySharedPrefs", FileCreationMode.Private);
            var prefsEditor = prefs.Edit();

            prefEditor.PutString("AccessToken", accessToken);
            prefEditor.Commit();
        }
    }
}
  

Я хотел бы написать код для конкретной платформы в MyPage LogIn методе сохранения токена доступа в зависимости от того, на какой ОС устройства они используют мое приложение.

Как мне запускать специфичный для устройства код только тогда, когда пользователь использует мое приложение на своем устройстве?

Ответ №1:

Это сценарий, который легко решается с помощью внедрения зависимостей.

Иметь интерфейс с желаемыми методами в вашем общем коде или коде PCL, например:

 public interface IUserPreferences 
{
    void SetString(string key, string value);
    string GetString(string key);
}
  

Создайте свойство для своего App класса этого интерфейса:

 public class App 
{
    public static IUserPreferences UserPreferences { get; private set; }

    public static void Init(IUserPreferences userPreferencesImpl) 
    {
        App.UserPreferences = userPreferencesImpl;
    }

    (...)
}
  

Создавайте реализации, зависящие от платформы, в ваших целевых проектах:

iOS:

 public class iOSUserPreferences : IUserPreferences 
{
    public void SetString(string key, string value)
    {
        NSUserDefaults.StandardUserDefaults.SetString(value, key);
    }

    public string GetString(string key)
    {
        return NSUserDefaults.StandardUserDefaults.StringForKey(key);
    }
}
  

Android:

 public class AndroidUserPreferences : IUserPreferences
{
    public void SetString(string key, string value)
    {
        var prefs = Application.Context.GetSharedPreferences("MySharedPrefs", FileCreationMode.Private);
        var prefsEditor = prefs.Edit();

        prefEditor.PutString(key, value);
        prefEditor.Commit();
    }

    public string GetString(string key)
    {
        (...)
    }
}
  

Затем в каждом проекте, зависящем от платформы, создайте реализацию IUserPreferences и установите ее, используя App.Init(new iOSUserPrefernces()) App.Init(new AndroidUserPrefernces()) методы либо и .

Наконец, вы можете изменить свой код на:

 public class MyPage : ContentPage
{
    public MyPage()
    {
        //do work to initialize MyPage 
    }

    public void LogIn(object sender, EventArgs eventArgs)
    {
        bool isAuthenticated = false;
        string accessToken = string.Empty;

        //do work to use authentication API to validate users

        if(isAuthenticated)
        {
            App.UserPreferences.SetString("AccessToken", accessToken);
        }
    }
}
  

Комментарии:

1. Во App фрагменте кода класса я получаю сообщение «Метод должен иметь возвращаемый тип» при попытке его закодировать. Должен ли он иметь возвращаемый тип void ?

2. Метод init, вероятно, должен иметь void возвращаемый тип.

3. Это очень хорошее решение, которое организует код в каждом проекте, зависящем от платформы. Спасибо.

4. Спасибо Майклу и Вальдетеро за то, что указали на это и исправили это. Рад, что этот ответ вам подходит, я использую этот подход для нескольких различных функций, специфичных для платформы, к которым мне нужен доступ. Также стоит обратить внимание DependencyService , как упоминал Стефан Делькруа.

Ответ №2:

Xamarin.В Forms 2.3.4 представлен новый метод для этого:

 if (Device.RuntimePlatform == Device.Android)
{
    // Android specific code
}
else if (Device.RuntimePlatform == Device.iOS)
{
    // iOS specific code
}
else if (Device.RuntimePlatform == Device.UWP)
{
    // UWP specific code
}
  

Есть и другие платформы на выбор, вы можете ввести Device. в Visual Studio, и он покажет вам варианты.

Ответ №3:

Существует несколько ответов, в зависимости от того, чего вы хотите достичь, и типа вашего проекта:

Выполнять разный Xamarin.Forms код на разных платформах.
Используйте это, например, если вам нужны разные размеры шрифта на разных платформах:

 label.Font = Device.OnPlatform<int> (12, 14, 14);
  

Выполнить код, зависящий от платформы, в общем проекте (PCL)
Общим шаблоном является использование DI (внедрение зависимостей) для этого. Xamarin.Forms предоставляет простой DependencyService способ для этого, но используйте все, что хотите.

Выполните код, зависящий от платформы, в проекте shared (Shared Asset Project) Поскольку код компилируется для каждой платформы, вы можете обернуть свой код, зависящий от платформы #if __PLATFORM__ #endif , и поместить весь код в один файл. Проект платформы должен определять __IOS__ , __ANDROID__ и __WINDOWS_PHONE__ . Обратите внимание, что проект с общим ресурсом, содержащий Xaml код и, не будет хорошо работать для iOS Xamarin.Studio , и что наличие директив компилятора затрудняет чтение и тестирование вашего кода.

Комментарии:

1. В настоящее время я использую вариант 3 «Выполнить код, зависящий от платформы, в проекте shard (проект с общим ресурсом)» с синтаксисом __IOS__ and __ANDROID__ , но код, специфичный для Android, не отображается в Intellisense. Специфичный для iOS код отображается в Intellisense

2. @MichaelKniskern: измените цель сборки на Android, чтобы для нее был intellisense. и убедитесь (в настройках вашего проекта), что символ экспортирован. кстати, я нахожу забавным, что вы используете этот ответ и принимаете другой 🙂

3. Я решил выбрать ответ, который не зависел от функциональности Xamarin, потому что у меня были другие проблемы с пустым приложением (Xamarin. Формы общего доступа) тип проекта. Кроме того, необходимость каждый раз переключать запуск проекта, если вы хотите использовать код, зависящий от платформы, не идеальна.

Ответ №4:

Xamarin.Forms имеет встроенный инжектор зависимостей, если вы посмотрите их руководство в разделе для разработчиков на их веб-сайте (http://developer.xamarin.com/guides/cross-platform/xamarin-forms/dependency-service /)

Также есть замечательная библиотека, которую вы можете извлечь из NuGet / Github (https://github.com/aritchie/acr-xamarin-forms ), который будет обрабатывать требования к хранилищу, которые вы ищете … взгляните на службу настроек там, она даже будет обрабатывать сериализацию более сложных объектов.

Ответ №5:

Это похоже не Xamarin.Forms столько на использование значений по умолчанию, сколько на использование значений по умолчанию в PCL. Ознакомьтесь с репозиторием github Джеймса Монтеманьо для выполнения кроссплатформенных настроек по умолчанию.

Затем просто вызовите его статические методы для настройки / извлечения. Пакет nuget является Xam.Plugins.Settings .

Его можно использовать следующим образом:

 using Refractored.Xam.Settings;
  

 CrossSettings.Current.AddOrUpdateValue("AccessToken", accessToken);
var value = CrossSettings.Current.GetValueOrDefault<string>("AccessToken");