Xamarin.Mac 작동 방법How Xamarin.Mac works

그러나 대부분의 개발자는 걱정할 필요가 없습니다를 내부 "매직" 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.StringHttpClient등).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-c 메서드Exposing 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. 통해 이렇게 합니다 RegisterExport 특성입니다.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 호출 선택기를 사용 하 여 initrun입니다.In this example, the Objective-C runtime will now know about a class called MyClass with selectors called init and run.

대부분의 경우, 즉 개발자 무시할 수 있는 구현 세부 정보는 앱이 수신 하는 대부분의 콜백 중 하나가 됩니다 재정의 된 메서드를 통해 온 base 클래스 (같은 AppDelegate하십시오 DelegatesDataSources) 또는 작업 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.

생성자 실행Constructor runthrough

대부분의 경우에서 개발자는 노출 해야 앱의 C# 클래스 생성 API는 Objective-c 런타임에서 경우와 같이 위치에서 인스턴스화될 수 있도록 호출 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 앱에서 사용 하는 가장 일반적인 5 명의 생성자는 다음과 같습니다.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)
{
}

일반적으로 개발자 유지 해야 합니다 IntPtrNSCoder 일부 유형을 사용자 지정 등을 만들 때 생성 되는 생성자 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.

계속 해 서 of time 컴파일이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에 따른 제한으로 인해 IL 코드의 JIT 컴파일 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을 사용 하는 하이브리드 되지만 사용 하면 필요한 trampolines 컴파일하고 계속 Reflection.Emit을 지원할 수 있는 유연성 런타임이 필요한 컴퓨터 코드의 대부분을 컴파일되지 않는 AOT 접근 방식 (및 다른 사용 사례에 현재 작업할 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:

  • "네이티브" 크래시 로그를 더 나은 -Cocoa Api를 잘못 된 호출을 수행할 때 자주 발생 되는 네이티브 코드에서 Xamarin.Mac 응용 프로그램 충돌 하는 경우 (보내는 등을 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 프레임에 디버그 정보가 없는, 때문에 16 진수 오프셋을 사용 하 여 여러 줄 고 어떤 알 수 없습니다 수 됩니다.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 "real" 명명 된 프레임을 생성 하 고 추적이 훨씬 쉽게 읽을 수 있습니다.AOT generates "real" named frames and the traces are much easier to read. 즉, Xamarin.Mac 앱은 더 잘 도구와 상호 작용 네이티브와 같은 lldb 하 고 계측합니다.This also means Xamarin.Mac app will interact better with native tools such as lldb and Instruments.
  • 시간 성능을 더 잘 실행 -여러 두 번째 시작 시간, JIT 컴파일 코드의 모든 큰 Xamarin.Mac 응용 프로그램에서 시간이 많이 걸릴 수 있습니다.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.

AOT 컴파일 사용Enabling 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 추가 mmp 인수 추가Adding 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.

Aot 컴파일 옵션Aot 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하십시오 Systemmscorlib 어셈블리.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 IL 제거를 허용 하는 하지만 결과에서 더 이상 컴파일되지 번이 위의 옵션 중 하나를 추가 합니다.|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 배 개선 거의 등록자 란, 정적 및 동적 간의 차이점은,이 "부분 정적" 버전의 용도에 배경의 약간 걸립니다.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 내부에서 응용 프로그램에는 Apple 및 Objective-c 런타임에서 Cocoa framework 있다는 점입니다.Under the hood of any Xamarin.Mac application lies the Cocoa framework from Apple and the Objective-C runtime. 이 "네이티브 world"의 "관리 되는 world" 사이의 연결을 구축 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. Xamarin.mac에서 Cocoa Api를 사용 해야 하는 한 가지 이유 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:

  • 정적 등록 시작 시간을 감소 시킬 수 있지만 속도가 느려집니다 빌드 시간이 크게 (2 배 이상의 일반적으로 디버그 빌드 시간).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.
  • 동적 등록이 작업 때까지 지연이 추가 작업을 눈에 띄는 일시 중지 (최소: 2 초)을 만들 수 있지만 응용 프로그램 시작 및 코드 생성을 건너뛰고 응용 프로그램 시작에.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 사용 하 여이 정보를 전달, Microsoft 제거 대부분의 동적 리플렉션 시간 빌드 시간에 영향을 주지 하는 동안 등록 기관입니다.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:

추가 mmp 인수 부분 정적 등록 기관에 추가할Adding the partial static registrar to additional mmp arguments

추가 자료Additional resources

작업 내부적으로 작업 하는 방법에 대 한 보다 자세한 설명을 다음과 같습니다.Here are some more detailed explanations of how things work internally: