통합 API 개요

Xamarin의 통합 API를 사용하면 Mac과 iOS 간에 코드를 공유하고 동일한 이진 파일로 32비트 및 64비트 애플리케이션을 지원할 수 있습니다. 통합 API는 기본적으로 새 Xamarin.iOS 및 Xamarin.Mac 프로젝트에서 사용됩니다.

Important

통합 API 이전의 Xamarin 클래식 API는 더 이상 사용되지 않습니다.

  • 클래식 API(monotouch.dll)를 지원하는 Xamarin.iOS의 마지막 버전은 Xamarin.iOS 9.10이었습니다.
  • Xamarin.Mac은 클래식 API를 계속 지원하지만 더 이상 업데이트되지 않습니다. 더 이상 사용되지 않으므로 개발자는 애플리케이션을 통합 API로 이동해야 합니다.

클래식 API 기반 앱 업데이트

플랫폼에 대한 관련 지침을 따릅니다.

코드를 Unified API로 업데이트하는 팁

마이그레이션하는 애플리케이션에 관계없이 통합 API를 성공적으로 업데이트하는 데 도움이 되도록 이러한 팁을 검사.

라이브러리 분할

이 시점부터 API는 다음 두 가지 방법으로 표시됩니다.

  • 클래식 API: 32비트(전용)로 제한되고 및 XamMac.dll 어셈블리에 monotouch.dll 노출됩니다.
  • 통합 API: 어셈블리에서 사용할 수 있는 Xamarin.iOS.dll 단일 API를 사용하여 32비트 및 Xamarin.Mac.dll 64비트 개발을 모두 지원합니다.

즉, 엔터프라이즈 개발자(App Store를 대상으로 하지 않음)의 경우 기존 클래식 API를 계속 사용할 수 있습니다. 기본 영구적으로 유지하거나 새 API로 업그레이드할 수 있습니다.

네임스페이스 변경 내용

Mac과 iOS 제품 간의 코드 공유 마찰을 줄이기 위해 제품의 API에 대한 네임스페이스를 변경하고 있습니다.

iOS 제품에서 "MonoTouch" 접두사를 삭제하고 Mac 제품의 "MonoMac"을 데이터 형식으로 삭제합니다.

이렇게 하면 조건부 컴파일에 의존하지 않고 Mac과 iOS 플랫폼 간에 코드를 더 간단하게 공유할 수 있으며 소스 코드 파일 맨 위에 있는 노이즈가 줄어듭니다.

  • 클래식 API: 네임스페이스가 사용 MonoTouch. 하거나 MonoMac. 접두사를 사용합니다.
  • 통합 API: 네임스페이스 접두사 없음

런타임 기본값

기본적으로 Unified API는 SGen 가비지 수집기 및 새 참조 계산 시스템을 사용하여 개체 소유권을 추적합니다. 이 동일한 기능이 Xamarin.Mac으로 이식되었습니다.

이렇게 하면 개발자가 이전 시스템에 직면한 여러 가지 문제가 해결되고 메모리 관리가 용이합니다.

클래식 API에 대해서도 새 Refcount를 사용하도록 설정할 수 있지만 기본값은 보수적이며 사용자가 변경할 필요가 없습니다. Unified API를 사용하여 기본값을 변경하고 개발자에게 코드를 리팩터링하고 다시 테스트하는 동시에 모든 개선 사항을 제공했습니다.

API 변경

Unified 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에서 사용할 수 없습니다. 올바른 API로 안내하는 특성 메시지(경고의 [Obsolete] 일부)가 있으므로 (수동 또는 자동화된) 업그레이드를 시작하기 전에 경고를 보다 쉽게 해결할 CS0616 수 있습니다.

프로젝트 업데이트 전후에 사용할 수 있는 클래식 및 통합 API 변경 내용을 게시합니다. 클래식에서 사용되지 않는 호출을 여전히 수정하는 것은 종종 시간 절약(문서 조회가 적음)입니다.

다음 지침에 따라 기존 iOS 앱 또는 Mac 앱을 통합 API로 업데이트합니다. 코드 마이그레이션에 대한 추가 정보는 이 페이지의 다시 기본 및 이러한 팁을 검토하세요.

NuGet

이전에 클래식 API를 통해 Xamarin.iOS를 지원했던 NuGet 패키지는 Monotouch10 플랫폼 모니커를 사용하여 어셈블리를 게시했습니다.

통합 API는 호환되는 패키지인 Xamarin.iOS10에 대한 새 플랫폼 식별자를 도입했습니다. 통합 API에 대해 빌드하여 이 플랫폼에 대한 지원을 추가하려면 기존 NuGet 패키지를 업데이트해야 합니다.

Important

"오류 3 동일한 Xamarin.iOS 프로젝트에 'monotouch.dll'과 'Xamarin.iOS.dll'을 모두 포함할 수 없습니다. 'Xamarin.iOS.dll'은 명시적으로 참조됩니다. 애플리케이션을 통합 API로 변환한 후 'xxx, Version=0.0.000, Culture=neutral, PublicKeyToken=null'에서 'monotouch.dll'을 참조하지만 일반적으로 통합 API로 업데이트되지 않은 프로젝트에 구성 요소 또는 NuGet 패키지가 있기 때문입니다. 기존 구성 요소/NuGet을 제거하고 통합 API를 지원하는 버전으로 업데이트하고 클린 빌드를 수행해야 합니다.

64비트로 가는 길

32비트 및 64비트 애플리케이션 지원 배경 및 프레임워크에 대한 자세한 내용은 32비트 및 64비트 플랫폼 고려 사항을 참조 하세요.

새 데이터 형식

이 차이의 핵심은 Mac과 iOS API 모두 32비트 플랫폼에서 항상 32비트이고 64비트 플랫폼에서는 64비트인 아키텍처별 데이터 형식을 사용합니다.

예를 들어 Objective-C 데이터 형식 int32_tNSInteger 32비트 시스템과 64비트 시스템에 int64_t 매핑합니다.

이 동작과 일치하기 위해 통합 API에서 이전 사용 int (.NET에서 항상 있는 System.Int32것으로 정의됨)을 새 데이터 형식 System.nint으로 바꿉니다. "n"은 "네이티브"를 의미하는 것으로 생각할 수 있으므로 플랫폼의 네이티브 정수 형식입니다.

필요한 경우 이를 기반으로 빌드된 데이터 형식을 소개 nintnuint 하고 nfloat 있습니다.

이러한 데이터 형식 변경에 대한 자세한 내용은 네이 티브 형식 문서를 참조하세요.

iOS 앱의 아키텍처를 검색하는 방법

애플리케이션이 32비트 또는 64비트 iOS 시스템에서 실행되는지 알아야 하는 상황이 있을 수 있습니다. 다음 코드를 사용하여 아키텍처를 검사 수 있습니다.

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

Arrays 및 System.Collections.Generic

C# 인덱서에는 형식int이 예상되므로 컬렉션 또는 배열의 요소에 액세스하기 위해 int 명시적으로 값을 캐스팅 nint 해야 합니다. 예시:

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

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

이는 64비트에서 intnint 캐스팅이 손실되므로 암시적 변환이 수행되지 않으므로 예상되는 동작입니다.

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 및 오타

Xamarin.iOS 클래식 API(monotouch.dll) [Obsolete] 내에서 특성은 다음과 같은 두 가지 방법으로 사용되었습니다.

  • 사용되지 않는 iOS API: Apple이 최신 API로 대체되기 때문에 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

통합 API NSAction 를 사용하면 표준 .NET Action을 위해 제거되었습니다. 이는 일반적인 .NET 형식인 반면 NSAction Xamarin.iOS와 관련이 있기 때문에 Action 크게 개선되었습니다. 둘 다 정확히 동일한 작업을 수행하지만 고유하고 호환되지 않는 형식이었으며 동일한 결과를 얻기 위해 더 많은 코드를 작성해야 했습니다.

예를 들어 기존 Xamarin 애플리케이션에 다음 코드가 포함된 경우

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

이제 간단한 람다로 바꿀 수 있습니다.

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

이전에는 할당NSAction할 수 없기 때문에 Action 컴파일러 오류가 발생했지만 UITapGestureRecognizer 이제 Action 는 통합 API에서 유효한 대신 NSAction 이 오류가 발생합니다.

작업<T로 대체된 사용자 지정 대리자>

통합된 일부 단순(예: 하나의 매개 변수)에서 .net 대리자는 .net 대리자로 Action<T>대체되었습니다. 예를 들어

public delegate void NSNotificationHandler (NSNotification notification);

는 이제 .로 Action<NSNotification>사용할 수 있습니다. 이렇게 하면 Xamarin.iOS 및 사용자 고유의 애플리케이션 내에서 코드를 다시 사용하고 코드 중복을 줄일 수 있습니다.

작업<부> 울이 작업<부울, NSError로 대체됨>>

클래식에서는 일부 비동기 API가 반환되었습니다Task<bool>. 그러나 그 중 일부는 서명의 일부일 때 NSError 사용해야 하는 위치입니다. bool 즉, 이미 true 있었고 예외를 catch하여 를 가져와 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가 내부 및 XamMac.dll내부에 monotouch.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를 더 쉽게 사용할 수 있으며, IDE 코드 완성은 프로토콜/인터페이스를 기반으로 보다 유용한 제안을 제공합니다.

NSCoding 프로토콜

원래 바인딩에는 프로토콜을 지원하지 않더라도 모든 형식에 대한 .ctor(NSCoder)가 NSCoding 포함되어 있습니다. 개체를 인코딩하기 위해 단일 Encode(NSCoder) 메서드가 있었습니다 NSObject . 그러나 이 메서드는 인스턴스가 NSCoding 프로토콜을 준수하는 경우에만 작동합니다.

통합 API에서 이 문제가 해결되었습니다. 새 어셈블리에는 형식이 준수NSCoding되는 .ctor(NSCoder) 경우에만 있습니다. 또한 이러한 형식에는 이제 인터페이스를 Encode(NSCoder) 준수하는 메서드가 있습니다 INSCoding .

낮은 영향: 대부분의 경우 이 변경 내용은 이전, 제거된 생성자를 사용할 수 없으므로 애플리케이션에 영향을 주지 않습니다.

추가 팁

알아야 할 추가 변경 내용은 통합 API앱을 업데이트하기 위한 팁에 나열되어 있습니다.