Как работает Xamarin.MacHow Xamarin.Mac works

В большинстве случаев разработчик будет никогда не нужно беспокоиться о внутренней «magic» xamarin.Mac, тем не менее, наличие грубого понимание того, как работает вещей взгляд изнутри помогут в обоих интерпретирующего существующую документацию с C# группы связанных элементов и отладка проблемы при их возникновении.Most of the time the developer will never have to worry about the internal "magic" of Xamarin.Mac, however, having a rough understanding of how things works under the hood will help in both interpreting existing documentation with a C# lens and debugging issues when they arise.

В Xamarin.Mac приложение связывает двух миров: Objective-C на основе среды выполнения, содержащая экземпляры собственные классы (NSString, NSApplicationи т. д) и имеется C# среды выполнения, содержащая экземпляры управляемые классы (System.String, HttpClientи т. д).In Xamarin.Mac, an application bridges two worlds: There is the Objective-C based runtime containing instances of native classes (NSString, NSApplication, etc) and there is the C# runtime containing instances of managed classes (System.String, HttpClient, etc). Между этими двумя мирами Xamarin.Mac создает два способа моста, поэтому приложение может вызывать методы (селекторы) на Objective-C (такие как NSApplication.Init) и Objective-C может вызвать приложение C# методы резервного (например, методы в делегат приложения).In between these two worlds, Xamarin.Mac creates a two way bridge so an app can call methods (selectors) in Objective-C (such as NSApplication.Init) and Objective-C can call the app's C# methods back (like methods on an app delegate). В общем случае вызовы в Objective-C обрабатываются прозрачно через P/Invoke и кода среды выполнения, Xamarin предоставляет.In general, calls into Objective-C are handled transparently via P/Invokes and some runtime code Xamarin provides.

Предоставление доступа к C# классы и методы для Objective-CExposing C# classes / methods to Objective-C

Тем не менее для Objective-C, выполнить обратный вызов приложения C# объекты, они должны быть доступны в виде, можно понять, Objective-C.However, for Objective-C to call back into an app's C# objects, they need to be exposed in a way that Objective-C can understand. Это делается с помощью Register и Export атрибуты.This is done via the Register and Export attributes. Рассмотрим следующий пример:Take the following example:

[Register ("MyClass")]
public class MyClass : NSObject
{
   [Export ("init")]
   public MyClass ()
   {
   }

   [Export ("run")]
   public void Run ()
   {
   }
}

В этом примере среда выполнения Objective-C, теперь будут знать о класс с именем MyClass с именем селекторы init и run.In this example, the Objective-C runtime will now know about a class called MyClass with selectors called init and run.

В большинстве случаев это деталь реализации, разработчик может игнорировать, так как большинство обратные вызовы, приложение получает будет работать, либо с помощью переопределенные методы base классов (таких как AppDelegate, Delegates, DataSources) или на Действия передан в API-интерфейсы.In most cases, this is an implementation detail that the developer can ignore, as most callbacks an app receives will be either via overridden methods on base classes (such as AppDelegate, Delegates, DataSources) or on Actions passed into APIs. Во всех этих случаях Export атрибуты не требуются в C# кода.In all of those cases, Export attributes are not necessary in the C# code.

Конструктор runthroughConstructor runthrough

Во многих случаях разработчику потребуется предоставить доступ к приложения C# классы конструкцию API среды выполнения Objective-C, поэтому он может быть создан из мест, например, при вызове в Storyboard "или" XIB файлов.In many cases, the developer will need to expose the app's C# classes construction API to the Objective-C runtime so it can be instantiated from places such as when called in Storyboard or XIB files. Ниже приведены пять наиболее распространенных конструкторы, используемые в приложениях для Xamarin.Mac.Here are the five most common constructors used in Xamarin.Mac apps:

// Called when created from unmanaged code
public CustomView (IntPtr handle) : base (handle)
{
   Initialize ();
}

// Called when created directly from a XIB file
[Export ("initWithCoder:")]
public CustomView (NSCoder coder) : base (coder)
{
   Initialize ();
}

// Called from C# to instance NSView with a Frame (initWithFrame)
public CustomView (CGRect frame) : base (frame)
{
}

// Called from C# to instance NSView without setting the frame (init)
public CustomView () : base ()
{
}

// This is a special case constructor that you call on a derived class when the derived called has an [Export] constructor.
// For example, if you call init on NSString then you don’t want to call init on NSObject.
public CustomView () : base (NSObjectFlag.Empty)
{
}

В общем случае следует оставить разработчик IntPtr и NSCoder конструкторы, которые создаются при создании некоторых типов, таких как настраиваемые NSViews отдельно.In general, the developer should leave the IntPtr and NSCoder constructors that are generated when creating some types such as custom NSViews alone. Если вы удалили Xamarin.Mac необходимо вызвать один из этих конструкторов в ответ на запрос среде выполнения Objective-C, произойдет сбой приложения в машинном коде и сложно выявить точно проблему.If Xamarin.Mac needs to call one of these constructors in response to an Objective-C runtime request and you’ve removed it, the app will crash inside native code and it may be difficult to figure out exactly the issue.

Управление памятью и циклыMemory management and cycles

Управление памятью в Xamarin.Mac является во многих отношениях, очень похожа на Xamarin.iOS.Memory management in Xamarin.Mac is in many ways very similar to Xamarin.iOS. Он также является непростой проблемой, один выходит за рамки этого документа.It also is a complex topic, one beyond the scope of this document. См. в статье памяти и рекомендации по повышению производительности.Please read the Memory and Performance Best Practices.

Преимущества времени компиляцииAhead of time compilation

Как правило, приложений .NET не компилируются в машинный код при построении, вместо этого они компилируются в промежуточный слой называется код IL, который получает Just-In-Time (JIT) скомпилированные в машинный код при запуске приложения.Typically, .NET applications do not compile down to machine code when they are built, instead they compile to an intermediate layer called IL code that gets Just-In-Time (JIT) compiled to machine code when the app is launched.

Время, необходимое среда выполнения mono JIT-компиляцию этого кода может замедлить запуск приложения Xamarin.Mac на 20%, занять некоторое время для необходимых машинный код будет создан.The time that it takes the mono runtime to JIT compile this machine code can slow the launch of a Xamarin.Mac app by up to 20%, as it takes time for the necessary machine code to be generated.

Из-за ограничений, налагаемых Apple на устройствах iOS JIT-компиляция кода IL не доступен для Xamarin.iOS.Because of limitations imposed by Apple on iOS, JIT compilation of the IL code is not available to Xamarin.iOS. В результате все приложения Xamarin.iOS полны Ahead-Of-Time (AOT) компиляции в машинный код в процессе построения.As a result, all Xamarin.iOS app are full Ahead-Of-Time (AOT) compiled to machine code during the build cycle.

Новый на Xamarin.Mac является возможность AOT код IL в процессе построения приложения так же, как можно Xamarin.iOS.New to Xamarin.Mac is the ability to AOT the IL code during the app build cycle, just like Xamarin.iOS can. Использует Xamarin.Mac гибридных AOT подход, который компилирует большую часть необходимых машинный код, но позволяет среде выполнения для компиляции необходимые trampolines и характеризуется гибкостью, продолжают поддерживать Reflection.Emit (и других целей обращения, в настоящее время работает на Xamarin.Mac).Xamarin.Mac uses a Hybrid AOT approach that compiles a majority of the needed machine code, but allows the runtime to compile needed trampolines and the flexibility to continue to support Reflection.Emit (and other use cases that currently work on Xamarin.Mac).

Существует два основных областей, где AOT могут помочь приложения Xamarin.Mac.There are two major areas where AOT can help a Xamarin.Mac app:

  • Лучше журналы сбоев «собственных» - в случае сбоя приложения Xamarin.Mac в машинном коде, который является обычное дело при выполнении недопустимый вызовов в API-интерфейсов Cocoa (например, отправку null в метод, который не принимает ее) собственных журналов с помощью JIT-компилятора сбоев кадры трудны для анализа.Better "native" crash logs - If a Xamarin.Mac application crashes in native code, which is common occurrence when making invalid calls into Cocoa APIs (such as sending a null into a method that doesn't accept it), native crash logs with JIT frames are difficult to analyze. Так как фреймы JIT Нет отладочной информации, будет существовать несколько строк с помощью шестнадцатеричных смещения и не может понять, что происходило.Since the JIT frames do not have debug information, there will be multiple lines with hex offsets and no clue what was going on. AOT создает «настоящий» именованный кадров и трассировки гораздо удобнее для чтения.AOT generates "real" named frames and the traces are much easier to read. Это также означает приложения Xamarin.Mac будет улучшается взаимодействие с помощью собственных средств например lldb и Instruments.This also means Xamarin.Mac app will interact better with native tools such as lldb and Instruments.
  • Лучше запуска производительность во время — для больших приложений Xamarin.Mac с помощью нескольких запуска повторно, JIT-компиляция весь код может занять значительное время.Better launch time performance - For large Xamarin.Mac applications, with a multiple second startup time, JIT compiling all of the code can take a significant amount of time. AOT выполняет эту работу.AOT does this work up front.

Включение компиляции AOTEnabling AOT compilation

AOT включен в Xamarin.Mac, дважды щелкнув имя_проекта в обозревателе решений, переходе по адресу сборки Mac и добавление --aot:[options] для Дополнительные аргументы mmp: поле (где [options] — один или несколько параметров типа AOT элемента управления, см. ниже).AOT is enabled in Xamarin.Mac by double-clicking the Project Name in the Solution Explorer, navigating to Mac Build and adding --aot:[options] to the Additional mmp arguments: field (where [options] is one or more options to control the AOT type, see below). Пример:For example:

Добавление AOT дополнительные аргументы mmpAdding AOT to additional mmp arguments

Важно!

Включение AOT компиляции значительно увеличивает время сборки, иногда до нескольких минут, но оно может улучшить время запуска приложения в среднем на 20%.Enabling AOT compilation dramatically increases build time, sometimes up to several minutes, but it can improve app launch times by an average of 20%. В результате компиляции AOT следует включать только на выпуска сборки приложения Xamarin.Mac.As a result, AOT compilation should only be enabled on Release builds of a Xamarin.Mac app.

Параметры компиляции AOTAot compilation options

Существует несколько различных параметров, которые можно настраивать при включении AOT-компиляцию для приложения Xamarin.Mac.There are several different options that can be adjusted when enabling AOT compilation on a Xamarin.Mac app:

  • none — Должен отсутствовать компиляция AOT.none - No AOT compilation. Этот параметр используется по умолчанию.This is the default setting.
  • all -AOT компиляция каждая сборка MonoBundle.all - AOT compiles every assembly in the MonoBundle.
  • core -Компиляция AOT Xamarin.Mac, System и mscorlib сборок.core - AOT compiles the Xamarin.Mac, System and mscorlib assemblies.
  • sdk -Компиляция AOT Xamarin.Mac и сборки библиотеки базовых классов (BCL).sdk - AOT compiles the Xamarin.Mac and Base Class Libraries (BCL) assemblies.
  • |hybrid — Добавление это одно из перечисленных выше включает гибридную компиляцию AOT, что позволяет исключить промежуточный язык, но будет приводят к увеличению времени компиляции.|hybrid - Adding this to one of the above options enables hybrid AOT which allows for IL stripping, but will result in longer compile times.
  • + — Включает в себя один файл для компиляции AOT.+ - Includes a single file for AOT compilation.
  • - — Удаляет файл из компиляции AOT.- - Removes a single file from AOT compilation.

Например --aot:all,-MyAssembly.dll позволит компиляция AOT на все сборки в MonoBundle за исключением MyAssembly.dll и --aot:core|hybrid,+MyOtherAssembly.dll,-mscorlib.dll бы Включение в гибридной среде, включите код AOT MyOtherAssembly.dll и исключение mscorlib.dll.For example, --aot:all,-MyAssembly.dll would enable AOT compilation on all of the assemblies in the MonoBundle except MyAssembly.dll and --aot:core|hybrid,+MyOtherAssembly.dll,-mscorlib.dll would enable hybrid, code AOT include the MyOtherAssembly.dll and excluding the mscorlib.dll.

Частичные статический регистратораPartial static registrar

При разработке приложения Xamarin.Mac, сводя к минимуму время между завершение, изменение и его тестирование может стать важным к соблюдению сроков разработки.When developing a Xamarin.Mac app, minimizing the time between completing a change and testing it can become important to meeting development deadlines. Стратегии например модульность базы кода и модульные тесты может помочь позволяет сократить время компиляции, так как они уменьшают количество раз, что приложение потребуется дорогостоящие полное перестроение.Strategies such as modularization of codebases and unit tests can help to decrease compile times, as they reduce the number of times that an app will require an expensive full rebuild.

Кроме того и знакомы с Xamarin.Mac, частичного статический регистратора (как впервые введены в Xamarin.iOS) может значительно сократить время запуска приложения Xamarin.Mac в Отладка конфигурации.Additionally, and new to Xamarin.Mac, Partial Static Registrar (as pioneered by Xamarin.iOS) can dramatically reduce the launch times of a Xamarin.Mac app in the Debug configuration. Понимание того, как можно с помощью частичного статический регистратора сжато почти улучшения в 5 раз в запуске отладки займет немного фона на такое регистратор, какова разница между статических и динамических и что делает эта версия «частичное static».Understanding how using the Partial Static Registrar can squeezed out an almost a 5x improvement in debug launch will take a bit of background on what the registrar is, what the difference is between static and dynamic, and what this “partial static” version does.

О регистраторAbout the registrar

Что скрывается за любой Xamarin.Mac приложения лежит платформа Cocoa Apple и среды выполнения Objective-C.Under the hood of any Xamarin.Mac application lies the Cocoa framework from Apple and the Objective-C runtime. Создание моста между этой «машинного кода» и «управляемым миром» C# является основной обязанностью Xamarin.Mac.Building a bridge between this "native world” and the "managed world” of C# is the primary responsibility of Xamarin.Mac. В рамках этого задания обрабатывается регистратор, который выполняется внутри NSApplication.Init () метод.Part of this task is handled by the registrar, which is executed inside NSApplication.Init () method. Это одна из причин, требующий использование API-интерфейсов Cocoa в Xamarin.Mac NSApplication.Init вызывается первой.This is one reason that any use of Cocoa APIs in Xamarin.Mac requires NSApplication.Init to be called first.

Задание регистратора — для информирования о существовании приложения среды выполнения Objective-C C# классы, производные от классов, таких как NSApplicationDelegate, NSView, NSWindow, и NSObject.The registrar’s job is to inform the Objective-C runtime of the existence of the app's C# classes that derive from classes such as NSApplicationDelegate, NSView, NSWindow, and NSObject. Это требует просмотра всех типов в приложении, чтобы определить, требующие регистрации и какие элементы на каждого типа отчета.This requires a scan of all types in the app to determine what needs registering and what elements on each type to report.

Такая проверка может выполняться либо динамически, при запуске приложения с помощью отражения, или статически, в качестве шага время сборки.This scan can be done either dynamically, at startup of the application with reflection, or statically, as a build time step. При выборе типа регистрации, разработчику следует иметь в виду следующие:When picking a registration type, the developer should be aware of the following:

  • Статические регистрации может значительно сократить время запуска, но может замедлить раз сборок значительно (обычно более чем в два раза время отладочной сборки).Static registration can drastically reduce launch times, but can slow down builds times significantly (typically more than double debug build time). Это будет по умолчанию для выпуска конфигурации построения.This will be the default for Release configuration builds.
  • Динамическая регистрация откладывается до этой работы приложения, запустите и пропускает создание кода, но дополнительной работы можно создать заметно паузу (по крайней мере две секунды) в запуска приложений.Dynamic registration delays this work until application launch and skips code generation, but this additional work can create a noticeable pause (at least two seconds) in application launch . Это особенно заметно в отладочных сборках конфигурации, который по умолчанию для динамической регистрации и занимает больше времени, отражения.This is especially noticeable in debug configuration builds, which defaults to dynamic registration and whose reflection is slower.

Частичные статические регистрации, впервые представленный в Xamarin.iOS 8.13 дает разработчику лучшее из обоих вариантов.Partial Static Registration, first introduced in Xamarin.iOS 8.13, gives the developer the best of both options. Путем предварительного вычисления сведения о регистрации каждого элемента в Xamarin.Mac.dll и доставки этих данных с помощью Xamarin.Mac в статической библиотеке (которому требуется только перейти во время сборки), как корпорация Майкрософт устранила большую часть времени отражения динамической Регистратор ущерба время сборки.By pre-computing the registration information of every element in Xamarin.Mac.dll and shipping this information with Xamarin.Mac in a static library (that only needs to be linked to at build time), Microsoft has removed most of the reflection time of the dynamic registrar while not impacting build time.

Включение частичного статический регистратораEnabling the partial static registrar

Частичные статический регистратор включен в Xamarin.Mac, дважды щелкнув имя_проекта в обозревателе решений, переходе по адресу сборки Mac и добавление --registrar:static для дополнительные аргументы mmp: поля.The Partial Static Registrar is enabled in Xamarin.Mac by double-clicking the Project Name in the Solution Explorer, navigating to Mac Build and adding --registrar:static to the Additional mmp arguments: field. Пример:For example:

Добавление частичного статический регистратор дополнительные аргументы mmpAdding the partial static registrar to additional mmp arguments

Дополнительные ресурсыAdditional resources

Ниже приведены более подробные пояснения сведениями о работе внутренним образом.Here are some more detailed explanations of how things work internally: