Общие сведения об унифицированных API

Унифицированный API Xamarin позволяет совместно использовать код между Mac и iOS и поддерживать 32 и 64-разрядные приложения с тем же двоичным файлом. Объединенный API используется по умолчанию в новых проектах Xamarin.iOS и Xamarin.Mac.

Внимание

Классический API Xamarin, предшествующий унифицированному API, устарел.

  • Последняя версия Xamarin.iOS для поддержки классического API (monotouch.dll) была Xamarin.iOS 9.10.
  • Xamarin.Mac по-прежнему поддерживает классический API, но он больше не обновляется. Так как он не рекомендуется, разработчики должны переместить свои приложения в единый API.

Обновление классических приложений на основе API

Следуйте соответствующим инструкциям для вашей платформы:

Советы по обновлению кода в Unified API

Независимо от того, какие приложения переносятся, проверка эти советы, чтобы помочь вам успешно обновить единый API.

Разделение библиотеки

С этого момента наши API будут отображаться двумя способами:

  • Классический API: ограничен 32-разрядными (только) и предоставляемыми в monotouch.dll сборках и XamMac.dll сборках.
  • Унифицированный API: поддержка как 32, так и 64-разрядной разработки с помощью одного API, доступного в Xamarin.iOS.dll сборках и Xamarin.Mac.dll сборках.

Это означает, что для разработчиков enterprise (не предназначенных для App Store), вы можете продолжать использовать существующие классические API, так как мы будем поддерживать их навсегда, или вы можете обновить до новых API.

Изменения пространства имен

Чтобы уменьшить трение по обмену кодом между нашими продуктами Mac и iOS, мы изменяем пространства имен для API в продуктах.

Мы удаляем префикс MonoTouch из нашего продукта iOS и MonoMac из нашего продукта Mac на типах данных.

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

  • Классический API: пространства имен используют MonoTouch. или MonoMac. префикс.
  • Унифицированный API: нет префикса пространства имен

Значения по умолчанию среды выполнения

Унифицированный API по умолчанию использует сборщик мусора SGen и новую систему подсчета ссылок для отслеживания владения объектами. Эта же функция была перенесена в Xamarin.Mac.

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

Обратите внимание, что можно включить new Refcount даже для классического API, но значение по умолчанию является консервативным и не требует внесения изменений пользователями. С помощью Единого API мы воспользовались возможностью изменения по умолчанию и дали разработчикам все улучшения одновременно, что они рефакторинг и повторно протестировали свой код.

Изменения API

Унифицированный API удаляет устаревшие методы и существует несколько экземпляров, в которых были опечатки в именах API, когда они были привязаны к исходным пространствам имен MonoTouch и MonoMac в классических API. Эти экземпляры были исправлены в новых унифицированных API и должны быть обновлены в ваших компонентах, приложениях iOS и Mac. Ниже приведен список наиболее распространенных, с которыми вы можете столкнуться:

Классическое имя метода API Имя метода унифицированного API
UINavigationController.PushViewControllerAnimated() UINavigationController.PushViewController()
UINavigationController.PopViewControllerAnimated() UINavigationController.PopViewController()
CGContext.SetRGBFillColor() CGContext.SetFillColor()
NetworkReachability.SetCallback() NetworkReachability.SetNotification()
CGContext.SetShadowWithColor CGContext.SetShadow
UIView.StringSize UIKit.UIStringDrawing.StringSize

Полный список изменений при переходе с классического на унифицированный API см. в документации по классическому (monotouch.dll) и единому (Xamarin.iOS.dll) api.

Обновление до единого

Несколько старых и устаревших API в классической версии недоступны в едином API. Вы можете упростить исправление CS0616 предупреждений перед запуском обновления (вручную или автоматической), так как у вас будет [Obsolete] сообщение атрибута (часть предупреждения), которое поможет вам перейти к правильному API.

Обратите внимание, что мы публикуем диффы классических и унифицированных изменений API, которые можно использовать до или после обновления проекта. По-прежнему исправление устаревших вызовов в классической версии часто будет экономией времени (меньше подстановок документации).

Следуйте этим инструкциям, чтобы обновить существующие приложения iOS или приложения Mac до единого API. Просмотрите оставшуюся часть этой страницы и дополнительные сведения о переносе кода.

NuGet

Пакеты NuGet, которые ранее поддерживали Xamarin.iOS через классический API, опубликовали свои сборки с помощью моникера платформы Monotouch10 .

Единый API представляет новый идентификатор платформы для совместимых пакетов — Xamarin.iOS10. Существующие пакеты NuGet должны быть обновлены для добавления поддержки этой платформы, создавая для единого API.

Внимание

Если в форме "Ошибка 3 не удается включить как monotouch.dll", так и "Xamarin.iOS.dll" в один и тот же проект Xamarin.iOS, ссылка на "Xamarin.iOS.dll" указана явным образом. хотя на "monotouch.dll" ссылается xxx, Version=0.0.000, Culture=neutral, PublicKeyToken=null" после преобразования приложения в объединенные API, обычно это связано с компонентом или пакетом NuGet в проекте, который не был обновлен до единого API. Необходимо удалить существующий компонент или NuGet, обновить до версии, поддерживающей объединенные API и выполнить чистую сборку.

Дорога к 64 битам

Общие сведения о поддержке 32 и 64-разрядных приложений и сведения о платформах см. в 32 и 64-разрядных рекомендациях по платформе.

Новые типы данных

В основе разницы api Mac и iOS используют типы данных, зависящие от архитектуры, которые всегда 32-разрядные на 32-разрядных платформах и 64-разрядных платформах.

Например, Objective-C сопоставляет NSInteger тип int32_t данных с 32-разрядными системами и int64_t с 64-разрядными системами.

Чтобы соответствовать этому поведению, в нашем унифицированном API мы заменяем предыдущие варианты использования int (которые в .NET определяются как всегдаSystem.Int32) новым типом данных: System.nint Вы можете считать "n" значением "native", поэтому собственный целочисленный тип платформы.

Мы представляем nintnuintnfloat и предоставляем типы данных, созданные на основе этих типов, где это необходимо.

Дополнительные сведения об этих изменениях типов данных см. в документе "Собственные типы ".

Определение архитектуры приложений iOS

Могут возникнуть ситуации, когда приложение должно знать, работает ли оно в 32-разрядной или 64-разрядной системе iOS. Следующий код можно использовать для проверка архитектуры:

if (IntPtr.Size == 4) {
    Console.WriteLine ("32-bit App");
} else if (IntPtr.Size == 8) {
    Console.WriteLine ("64-bit App");
}

Массивы и System.Collections.Generic

Так как индексаторы C# ожидают тип int, необходимо явно привести nint значения для int доступа к элементам в коллекции или массиве. Например:

public List<string> Names = new List<string>();
...

public string GetName(nint index) {
    return Names[(int)index];
}

Это ожидаемое поведение, так как приведение отсюда intnint теряется на 64-разрядном бите, неявное преобразование не выполняется.

Преобразование DateTime в NSDate

При использовании объединенных API неявное преобразование значений DateTimeNSDate больше не выполняется. Эти значения должны быть явно преобразованы из одного типа в другой. Для автоматизации этого процесса можно использовать следующие методы расширения:

public static DateTime NSDateToDateTime(this NSDate date)
{
    // NSDate has a wider range than DateTime, so clip
    // the converted date to DateTime.Min|MaxValue.
    double secs = date.SecondsSinceReferenceDate;
    if (secs < -63113904000)
        return DateTime.MinValue;
    if (secs > 252423993599)
        return DateTime.MaxValue;
    return (DateTime) date;
}

public static NSDate DateTimeToNSDate(this DateTime date)
{
    if (date.Kind == DateTimeKind.Unspecified)
        date = DateTime.SpecifyKind (date, /* DateTimeKind.Local or DateTimeKind.Utc, this depends on each app */)
    return (NSDate) date;
}

Устаревшие API и typeos

В классическом API Xamarin.iOS (monotouch.dll) [Obsolete] атрибут использовался двумя разными способами:

  • Нерекомендуемый API iOS: это когда Apple намекает на то, чтобы прекратить использование API, так как он заменен более новым. Классический API по-прежнему хорошо и часто требуется (если вы поддерживаете старую версию iOS). Такие API (и [Obsolete] атрибут) включаются в новые сборки Xamarin.iOS.
  • Неправильный API Некоторые API имели опечатки в их именах.

Для исходных сборок (monotouch.dll и XamMac.dll) мы сохранили старый код, доступный для совместимости, но они были удалены из сборок унифицированных API (Xamarin.iOS.dll и Xamarin.Mac)

Подклассы NSObject .ctor(IntPtr)

Каждый NSObject подкласс имеет конструктор, который принимает объект IntPtr. Вот как можно создать экземпляр нового управляемого экземпляра из собственного дескриптора ObjC.

В классической public версии это был конструктор. Однако было легко использовать эту функцию в пользовательском коде, например создание нескольких управляемых экземпляров для одного экземпляра ObjC или создание управляемого экземпляра, который не хватает ожидаемого управляемого состояния (для подклассов).

Чтобы избежать таких проблем IntPtr , конструкторы теперь protected находятся в едином API, которые будут использоваться только для подклассов. Это гарантирует, что правильный или безопасный API используется для создания управляемого экземпляра из дескрипторов, т. е.

var label = Runtime.GetNSObject<UILabel> (handle);

Этот API вернет существующий управляемый экземпляр (если он уже существует) или создаст новый (при необходимости). Он уже доступен как в классическом, так и в унифицированном API.

Обратите внимание, что сейчас он .ctor(NSObjectFlag) также, protected но он редко использовался за пределами подклассов.

NSAction заменен действием

При использовании объединенных NSAction API было удалено в пользу стандартной .NET Action. Это большое улучшение, так как это распространенный тип .NET, в то время как ActionNSAction это относится к Xamarin.iOS. Они оба делают точно то же самое, но они были отдельными и несовместимыми типами и привели к тому, что для достижения одного и того же результата необходимо записать больше кода.

Например, если существующее приложение Xamarin включало следующий код:

UITapGestureRecognizer singleTap = new UITapGestureRecognizer (new NSAction (delegate() {
    ShowDropDownAnimated (tblDataView);
}));

Теперь его можно заменить простой лямбда-код:

UITapGestureRecognizer singleTap = new UITapGestureRecognizer (() => ShowDropDownAnimated(tblDataView));

Ранее это была ошибка компилятора, так как Action не удается назначить NSAction, но с тех пор UITapGestureRecognizerAction принимает вместо допустимого NSAction в объединенных API.

Пользовательские делегаты, замененные действием<T>

В унифицированных некоторых простых (например, один параметр) делегатов .net были заменены Action<T>на . Пример:

public delegate void NSNotificationHandler (NSNotification notification);

теперь можно использовать в качестве Action<NSNotification>. Это способствует повторному использованию кода и сокращению дублирования кода как в Xamarin.iOS, так и в собственных приложениях.

Логическое> значение задачи заменено логическим значением задачи<<, NSError>>

В классической версии были некоторые асинхронные API, возвращающие Task<bool>. Однако некоторые из них, где следует использовать, когда NSError была частью подписи, т. е. bool это уже true было, и вам пришлось поймать исключение, чтобы получить NSError.

Так как некоторые ошибки очень распространены, и возвращаемое значение не было полезно для этого шаблона было изменено в унифицированном режиме для возврата Task<Tuple<Boolean,NSError>>. Это позволяет проверка успешное выполнение и любую ошибку, которая могла произойти во время асинхронного вызова.

NSString и строка

В некоторых случаях некоторые константы должны быть изменены с stringNSString, например. UITableViewCell

Классическое

public virtual string ReuseIdentifier { get; }

Единой

public virtual NSString ReuseIdentifier { get; }

Как правило, мы предпочитаем тип .NET System.String . Однако, несмотря на рекомендации Apple, некоторые собственные API сравнивают константные указатели (а не сама строка), и это может работать только в том случае, если мы предоставляем константы как NSString.

Objective-C Протоколы

Исходный MonoTouch не имеет полной поддержки протоколов ObjC, а некоторые, неоптимальные, API были добавлены для поддержки наиболее распространенных сценариев. Это ограничение больше не существует, но для обратной совместимости несколько API хранятся внутри monotouch.dll и XamMac.dll.

Эти ограничения были удалены и удалены в объединенных API. Большинство изменений будут выглядеть следующим образом:

Классическое

public virtual AVAssetResourceLoaderDelegate Delegate { get; }

Единой

public virtual IAVAssetResourceLoaderDelegate Delegate { get; }

Префикс I означает единый доступ к интерфейсу вместо определенного типа для протокола ObjC. Это позволит упростить ситуации, когда вы не хотите подклассить конкретный тип, предоставленный Xamarin.iOS.

Кроме того, некоторые API могут быть более точными и простыми в использовании, например:

Классическое

public virtual void SelectionDidChange (NSObject uiTextInput);

Единой

public virtual void SelectionDidChange (IUITextInput uiTextInput);

Такой API теперь проще для нас, без ссылки на документацию, и завершение кода интегрированной среды разработки предоставит вам более полезные предложения на основе протокола или интерфейса.

Протокол NSCoding

Наша исходная привязка включала ctor(NSCoder) для каждого типа, даже если она не поддерживала NSCoding протокол. Encode(NSCoder) Один метод присутствовал в NSObject кодировании объекта. Но этот метод будет работать только в том случае, если экземпляр соответствует протоколу NSCoding.

Исправлено это в едином API. Новые сборки будут иметь только те .ctor(NSCoder) , которые соответствуют типу NSCoding. Кроме того, такие типы теперь имеют Encode(NSCoder) метод, соответствующий интерфейсу INSCoding .

Низкое влияние: в большинстве случаев это изменение не повлияет на приложения как старые, удаленные, конструкторы не могут использоваться.

Дальнейшие Советы

Дополнительные изменения, которые следует учитывать, перечислены в советах по обновлению приложений до единого API.