플랫폼 간 앱에서의 네이티브 형식 작업Working with Native Types in Cross-Platform Apps

이 문서에서는 Android 또는 Windows Phone Os와 같은 비 iOS 장치와 코드를 공유 하는 플랫폼 간 응용 프로그램에서 새로운 iOS Unified API 네이티브 형식 (nint, nuint, nint)을 사용 하는 방법을 설명 합니다.This article covers using the new iOS Unified API Native types (nint, nuint, nfloat) in a cross-platform application where code is shared with non-iOS devices such as Android or Windows Phone OSes.

64 형식의 네이티브 형식은 iOS 및 Mac Api에서 작동 합니다.The 64-types native types work with the iOS and Mac APIs. Android 또는 Windows에서 실행 되는 공유 코드를 작성 하는 경우에는 공유할 수 있는 일반 .NET 형식으로 통합 형식을 변환 해야 합니다.If you are writing shared code that runs on Android or Windows as well, you'll need to manage the conversion of Unified types into regular .NET types that you can share.

이 문서에서는 공유/공통 코드에서 Unified API와 상호 작용 하는 다양 한 방법을 설명 합니다.This document discusses different ways to interoperate with the Unified API from your shared/common code.

네이티브 형식을 사용 하는 경우When to Use the Native Types

Xamarin.ios 및 Xamarin.ios 통합 Api에는 RectangleF, SizeFPointF 형식 뿐만 아니라 int, uintfloat 데이터 형식도 포함 되어 있습니다.Xamarin.iOS and Xamarin.Mac Unified APIs still include the int, uint and float data types, as well as the RectangleF, SizeF and PointF types. 이러한 기존 데이터 형식은 공유 플랫폼 간 코드에서 계속 사용 해야 합니다.These existing data types should continue to be used in any shared, cross-platform code. 아키텍처 인식 형식에 대 한 지원이 필요한 Mac 또는 iOS API를 호출할 때에만 새 네이티브 데이터 형식을 사용 해야 합니다.The new Native data types should only be used when making a call to a Mac or iOS API where support for architecture-aware types are required.

공유 되는 코드의 특성에 따라 플랫폼 간 코드가 nint, nuintnfloat 데이터 형식을 처리 해야 하는 경우가 있을 수 있습니다.Depending on the nature of the code being shared, there might be times where cross-platform code might need to deal with the nint, nuint and nfloat data types. 예를 들어 이전에 System.Drawing.RectangleF를 사용 하 여 Xamarin.ios 및 Xamarin Android 버전의 앱 간에 기능을 공유 하는 사각형 데이터의 변환을 처리 하는 라이브러리는 iOS에서 네이티브 형식을 처리 하도록 업데이트 해야 합니다.For example: a library that handles transformations on rectangular data that was previously using System.Drawing.RectangleF to share functionality between Xamarin.iOS and Xamarin.Android versions of an app, would need to be updated to handle Native Types on iOS.

이러한 변경을 처리 하는 방법은 다음 섹션에서 볼 수 있듯이 응용 프로그램의 크기와 복잡성과 사용 된 코드 공유의 형식에 따라 달라 집니다.How these changes are handled depends on the size and complexity of the application and the form of code sharing that has been used, as we will see in the following sections.

코드 공유 고려 사항Code Sharing Considerations

코드 공유 옵션 문서에 설명 된 대로 플랫폼 간 프로젝트 간에 코드를 공유 하는 두 가지 주요 방법으로 공유 프로젝트와 이식 가능한 클래스 라이브러리를 사용할 수 있습니다.As stated in the Sharing Code Options document, there are two main ways to sharing code between cross-platform projects: Shared Projects and Portable Class Libraries. 두 가지 형식이 사용 된 경우 플랫폼 간 코드에서 네이티브 데이터 형식을 처리할 때 사용 하는 옵션을 제한 합니다.Which of the two types has been used, will limit the options we have when handling the Native data types in cross-platform code.

이식 가능한 클래스 라이브러리 프로젝트Portable Class Library Projects

PCL (이식 가능한 클래스 라이브러리)을 사용 하면 지원 하려는 플랫폼을 대상으로 지정 하 고 인터페이스를 사용 하 여 플랫폼별 기능을 제공할 수 있습니다.A Portable Class Library (PCL) allows you to target the platforms you wish to support, and use interfaces to provide platform-specific functionality.

PCL 프로젝트 형식이 .DLL로 컴파일되고 Unified API에 적합 하지 않으므로 PCL 소스 코드에서 기존 데이터 형식 (int, uint, float)을 계속 사용 하 고, pcl의 클래스에 대 한 호출을 형식으로 캐스팅 해야 합니다. 프런트 엔드 응용 프로그램의 및 메서드.Since the PCL Project type is compiled down to a .DLL and it has no sense of the Unified API, you'll be forced to keep using the existing data types (int, uint, float) in the PCL source code and type cast the calls to the PCL's classes and methods in the front-end applications. 예를 들면,For example:

using NativePCL;
...

CGRect rect = new CGRect (0, 0, 200, 200);
Console.WriteLine ("Rectangle Area: {0}", Transformations.CalculateArea ((RectangleF)rect));

공유 프로젝트Shared Projects

공유 자산 프로젝트 형식을 사용 하면 별도의 프로젝트에서 소스 코드를 구성 하 고, 개별 플랫폼별 프런트 엔드 앱에 포함 하 고 컴파일한 다음, 플랫폼별를 관리 하는 데 필요한 #if 컴파일러 지시문을 사용할 수 있습니다. 사항이.The Shared Asset Project type allows you to organize your source code in a separate project that then gets included and compiled into the individual platform-specific front end apps, and use #if compiler directives as required to manage platform-specific requirements.

공유 되는 코드의 크기 및 복잡성과 함께 공유 코드를 사용 하는 프런트 엔드 모바일 응용 프로그램의 크기와 복잡성은 플랫폼 간 네이티브 데이터 형식에 대 한 지원 방법을 선택할 때 고려해 야 합니다. 공유 자산 프로젝트.The size and complexity of the front end mobile applications that are consuming shared code, along with the size and the complexity of the code being shared, needs to be taken into account when choosing the method of support for Native data types in a cross-platform Shared Asset Project.

이러한 요소에 따라 if __UNIFIED__ ... #endif 컴파일러 지시문을 사용 하 여 코드에 대 한 Unified API 특정 변경을 처리 하는 다음 유형의 솔루션을 구현할 수 있습니다.Based on these factors, the following types of solutions might be implemented using the if __UNIFIED__ ... #endif compiler directives to handle the Unified API specific changes to the code.

중복 메서드 사용Using Duplicate Methods

위에 지정 된 사각형 데이터에서 변환을 수행 하는 라이브러리의 예를 들어 보겠습니다.Take the example of a library that is doing transformations on rectangular data given above. 라이브러리에 매우 간단한 메서드를 하나 또는 두 개만 포함 하는 경우 Xamarin.ios 및 Xamarin.ios에 대 한 해당 메서드의 중복 버전을 만들도록 선택할 수 있습니다.If the library only contains one or two very simple methods, you might choose to create duplicate versions of those methods for Xamarin.iOS and Xamarin.Android. 예를 들면,For example:

using System;
using System.Drawing;

#if __UNIFIED__
using CoreGraphics;
#endif

namespace NativeShared
{
    public class Transformations
    {
        #region Constructors
        public Transformations ()
        {
        }
        #endregion

        #region Public Methods
        #if __UNIFIED__
            public static nfloat CalculateArea(CGRect rect) {

                // Calculate area...
                return (rect.Width * rect.Height);

            }
        #else
            public static float CalculateArea(RectangleF rect) {

                // Calculate area...
                return (rect.Width * rect.Height);

            }
        #endif
        #endregion
    }
}

위의 코드에서 CalculateArea 루틴은 매우 간단 하므로 조건부 컴파일을 사용 하 고 별도의 Unified API 버전의 메서드를 만들었습니다.In the above code, since the CalculateArea routine is very simple, we have used conditional compilation and created a separate, Unified API version of the method. 반면, 라이브러리에 여러 루틴 또는 복잡 한 루틴이 포함 된 경우이 솔루션은 수정 또는 버그 수정을 위해 모든 메서드를 동기화 상태로 유지 하는 문제를 제공 하기 때문에 불가능 합니다.On the other hand, if the library contained many routines or several complex routines, this solution would not be feasible, as it would present an issue keeping all of the methods in sync for modifications or bug fixes.

메서드 오버 로드 사용Using Method Overloads

이 경우 솔루션은 32 비트 데이터 형식을 사용 하 여 메서드의 오버 로드 버전을 만들어 이제 CGRect 매개 변수 및/또는 반환 값으로 사용 하도록 할 수 있습니다 .이 값을 RectangleF (nfloat에서로 변환 하는 것을 알고 float 는 손실 변환) 이며 원래 버전의 루틴을 호출 하 여 실제 작업을 수행 합니다.In that case, the solution might be to create an overload version of the methods using 32-bit data types so that they now take CGRect as a parameter and/or a return value, convert that value to a RectangleF (knowing that converting from nfloat to float is a lossy conversion), and call the original version of the routine to do the actual work. 예를 들면,For example:

using System;
using System.Drawing;

#if __UNIFIED__
using CoreGraphics;
#endif

namespace NativeShared
{
    public class Transformations
    {
        #region Constructors
        public Transformations ()
        {
        }
        #endregion

        #region Public Methods
        #if __UNIFIED__
            public static nfloat CalculateArea(CGRect rect) {

                // Call original routine to calculate area
                return (nfloat)CalculateArea((RectangleF)rect);

            }
        #endif

        public static float CalculateArea(RectangleF rect) {

            // Calculate area...
            return (rect.Width * rect.Height);

        }

        #endregion
    }
}

이는 정밀도 손실이 응용 프로그램의 특정 요구에 대 한 결과에 영향을 주지 않는 한 좋은 해결책입니다.Again, this is a good solution as long as the loss of precision doesn't affect the results for your application's specific needs.

별칭 지시문 사용Using Alias Directives

정밀도 손실이 문제가 되는 영역에 대 한 가능한 또 다른 해결 방법은 using 지시문을 사용 하 여 공유 소스 코드 파일의 맨 위에 다음 코드를 포함 하 고 필요한 것을 변환 하 여 네이티브 및 CoreGraphics 데이터 형식에 대 한 별칭을 만드는 것입니다 @no_ t_1, uint 또는 floatnint, nuint 또는 nfloat:For areas where the loss of precision is an issue, another possible solution is to use using directives to create an alias for Native and CoreGraphics data types by including the following code to the top of the shared source code files and converting any needed int, uint or float values to nint, nuint or nfloat:

#if __UNIFIED__
    // Mappings Unified CoreGraphic classes to MonoTouch classes
    using RectangleF = global::CoreGraphics.CGRect;
    using SizeF = global::CoreGraphics.CGSize;
    using PointF = global::CoreGraphics.CGPoint;
#else
    // Mappings Unified types to MonoTouch types
    using nfloat = global::System.Single;
    using nint = global::System.Int32;
    using nuint = global::System.UInt32;
#endif

그러면 예제 코드가 다음과 같이 됩니다.So that our example code then becomes:

using System;
using System.Drawing;

#if __UNIFIED__
    // Map Unified CoreGraphic classes to MonoTouch classes
    using RectangleF = global::CoreGraphics.CGRect;
    using SizeF = global::CoreGraphics.CGSize;
    using PointF = global::CoreGraphics.CGPoint;
#else
    // Map Unified types to MonoTouch types
    using nfloat = global::System.Single;
    using nint = global::System.Int32;
    using nuint = global::System.UInt32;
#endif

namespace NativeShared
{

    public class Transformations
    {
        #region Constructors
        public Transformations ()
        {
        }
        #endregion

        #region Public Methods
        public static nfloat CalculateArea(RectangleF rect) {

            // Calculate area...
            return (rect.Width * rect.Height);

        }
        #endregion
    }
}

여기서는 표준 float대신 nfloat을 반환 하도록 CalculateArea 메서드를 변경 했습니다.Note that here we have changed the CalculateArea method to return an nfloat instead of the standard float. 이렇게 하면 계산의 nfloat 결과를 암시적 으로 변환 하는 컴파일 오류가 발생 하지 않습니다. (두 값 모두 nfloat형식) float 반환 값으로 변환 됩니다.This was done so that we would not get a compile error trying to implicitly convert the nfloat result of our calculation (since both values being multiplied are of type nfloat) into a float return value.

코드가 컴파일되고 Unified API 되지 않은 장치에서 실행 되는 경우 using nfloat = global::System.Single;nfloatSingle에 매핑합니다. 그러면 사용 중인 프런트 엔드 응용 프로그램에서 수정 하지 않고 float 메서드를 호출할 수 있습니다.If the code is compiled and run on a non Unified API device, the using nfloat = global::System.Single; maps the nfloat to a Single which will implicitly convert to a float allowing the consuming front-end application to call the CalculateArea method without modification.

프런트 엔드 앱에서 형식 변환 사용Using Type Conversions in the Front End App

프런트 엔드 응용 프로그램에서 공유 코드 라이브러리에 대해 몇 개의 호출만 수행 하는 경우 다른 해결 방법은 기존 루틴을 호출할 때 라이브러리를 변경 하지 않고, Xamarin.ios 또는 Xamarin.ios 응용 프로그램에서 형식 캐스팅을 수행 하는 것입니다.In the event that your front end applications only make a handful of calls to your shared code library, another solution could be to leave the library unchanged and do type casting in the Xamarin.iOS or Xamarin.Mac application when calling the existing routine. 예를 들면,For example:

using NativeShared;
...

CGRect rect = new CGRect (0, 0, 200, 200);
Console.WriteLine ("Rectangle Area: {0}", Transformations.CalculateArea ((RectangleF)rect));

소비 하는 응용 프로그램에서 공유 코드 라이브러리를 수백 번 호출 하는 경우에는이 방법이 좋은 솔루션이 아닐 수 있습니다.If the consuming application makes hundreds of calls to the shared code library, this again, might not be a good solution.

응용 프로그램의 아키텍처에 따라 위의 솔루션 중 하나 이상을 사용 하 여 플랫폼 간 코드에서 네이티브 데이터 형식 (필요한 경우)을 지원할 수 있습니다.Based on our application's architecture, we might end up using one or more of the above solutions to support Native Data Types (where required) in our cross-platform code.

Xamarin Forms 응용 프로그램Xamarin.Forms Applications

다음은 Unified API 응용 프로그램과 공유 되는 플랫폼 간 Ui에 대해 Xamarin.ios를 사용 하는 데 필요 합니다.The following is required to use Xamarin.Forms for cross-platform UIs that will also be shared with a Unified API application:

  • 전체 솔루션은 Xamarin.ios NuGet 패키지 버전을 1.3.1 이상 사용 해야 합니다.The entire solution must be using version 1.3.1 (or greater) of the Xamarin.Forms NuGet Package.
  • Xamarin.ios 사용자 지정 렌더링의 경우 UI 코드가 공유 된 방법 (공유 프로젝트 또는 PCL)에 따라 위에 표시 된 것과 동일한 유형의 솔루션을 사용 합니다.For any Xamarin.iOS custom renders, use the same types of solutions presented above based on how the UI code has been shared (Shared Project or PCL).

표준 플랫폼 간 응용 프로그램과 마찬가지로, 대부분의 경우 모든 공유 플랫폼 간 코드에서 기존 32 비트 데이터 형식을 사용 해야 합니다.As in a standard cross-platform application, the existing 32-bit data types should be used in any shared, cross-platform code for most situations. 아키텍처 인식 형식에 대 한 지원이 필요한 Mac 또는 iOS API를 호출할 때에만 새 네이티브 데이터 형식을 사용 해야 합니다.The new Native Data Types should only be used when making a call to a Mac or iOS API where support for architecture-aware types is required.

자세한 내용은 기존 Xamarin.ios 앱 업데이트 설명서를 참조 하세요.For more details, see our Updating Existing Xamarin.Forms Apps documentation.

요약Summary

이 문서에서는 Unified API 응용 프로그램에서 네이티브 데이터 형식을 사용 하는 시기와 플랫폼 간 영향을 살펴보았습니다.In this article we have seen when to use the Native Data Types in a Unified API application and their implications cross-platform. 플랫폼 간 라이브러리에서 새 네이티브 데이터 형식을 사용 해야 하는 경우에 사용할 수 있는 여러 가지 솔루션을 제공 합니다.We have presented several solutions that can be used in situations where the new Native Data Types must be used in cross-platform libraries. 또한 Xamarin. Forms 플랫폼 간 응용 프로그램에서 통합 Api를 지 원하는 간단한 가이드를 살펴보았습니다.Also, we've seen a quick guide to supporting Unified APIs in Xamarin.Forms cross-platform applications.