将绑定迁移到 Unified API

本文提供必要步骤,介绍如何更新现有 Xamarin 绑定项目来支持对 Xamarin.IOS 和 Xamarin.Mac 应用程序使用 Unified API。

概述

从 2015 年 2 月 1 日起,Apple 要求向 iTunes 和 Mac App Store 提交的所有新内容都必须是 64 位应用程序。 因此,为了支持 64 位,所有新的 Xamarin.iOS 或 Xamarin.Mac 应用程序都需要使用新的 Unified API 而不是现有的 Classic MonoTouch 和 MonoMac API。

此外,所有 Xamarin 绑定项目也必须支持要包含在 64 位 Xamarin.iOS 或 Xamarin.Mac 项目中的新的 Unified API。 本文将介绍更新现有绑定项目来使用 Unified API 所需的步骤。

要求

要完成本文所述的步骤,需要满足以下条件:

  • Visual Studio for Mac - 在开发计算机上安装和配置的最新版本的 Visual Studio for Mac。
  • Apple Mac - 要生成适用于 iOS 和 Mac 的绑定项目,需要使用 Apple Mac。

Windows 计算机上的 Visual Studio 不支持绑定项目。

修改 Using 语句

借助 Unified API,可在 Mac 和 iOS 之间比以往更轻松地共享代码,还能使用相同的二进制文件支持 32 和 64 位应用程序。 通过从命名空间中删除 MonoMac 和 MonoTouch 前缀,可以跨 Xamarin.Mac 和 Xamarin.iOS 应用程序项目更简单地进行共享。

因此,我们需要修改我们的所有绑定协定(以及绑定项目中的其他 .cs 文件),以便从 using 语句中删除 MonoMac 和 MonoTouch 前缀。

例如,给定绑定协定中的以下 using 语句:

using System;
using System.Drawing;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using MonoTouch.ObjCRuntime;

我们将删除 MonoTouch 前缀,结果如下所示:

using System;
using System.Drawing;
using Foundation;
using UIKit;
using ObjCRuntime;

同样,我们需要对绑定项目中的所有 .cs 文件执行此操作。 完成此更改后,下一步是更新绑定项目以使用新的原生数据类型。

有关 Unified API 的详细信息,请参阅 Unified API 文档。 有关支持 32 位和 64 位应用程序的更多背景信息和框架相关信息,请参阅 32 位和 64 位平台注意事项文档。

更新到原生数据类型

Objective-C 在 32 位系统上将 NSInteger 数据类型映射到 int32_t,在 64 位系统上则映射到 int64_t。 为了匹配此行为,新的 Unified API 将以前使用的 int(它在 .NET 中定义为始终是 System.Int32)替换为新的数据类型:System.nint

除了新的 nint 数据类型,Unified API 还引入了 nuintnfloat,用于映射到 NSUIntegerCGFloat 类型。

鉴于上述情况,我们需要查看 API,并确保之前映射到的 intuintfloatNSIntegerNSUIntegerCGFloat 的任何实例都更新为新的 nintnuintnfloat 类型。

例如,给定 Objective-C 方法定义如下:

-(NSInteger) add:(NSInteger)operandUn and:(NSInteger) operandDeux;

如果上一个绑定协定具有以下定义:

[Export("add:and:")]
int Add(int operandUn, int operandDeux);

我们会更新新绑定,使其如下所示:

[Export("add:and:")]
nint Add(nint operandUn, nint operandDeux);

如果我们要映射到比最初链接到的版本更新的第三方库,我们需要查看库的 .h 头文件,并查看对 intint32_tunsigned intuint32_tfloat 的任何现有显式调用是否已更新为 NSIntegerNSUIntegerCGFloat。 如果已经更新,需要对 nintnuintnfloat 类型和其映射进行相同的修改。

若要详细了解这些数据类型的变化,请参阅原生类型文档。

更新 CoreGraphics 类型

CoreGraphics 一起使用的点、大小和矩形数据类型根据运行它们的设备来使用 32 或 64 位。 当 Xamarin 最初绑定 iOS 和 Mac API 时,我们使用了与 System.Drawing 中的数据类型匹配的现有数据结构(例如 RectangleF)。

由于需要支持 64 位和新的原生数据类型,因此在调用 CoreGraphic 方法时,需要对现有代码进行以下调整:

  • CGRect - 在定义浮点矩形区域时使用 CGRect 而不是 RectangleF
  • CGSize - 在定义浮点大小(宽度和高度)时使用 CGSize 而不是 SizeF
  • CGPoint - 在定义浮点位置(X 和 Y 坐标)时使用 CGPoint 而不是 PointF

鉴于上述情况,我们需要查看 API,并确保之气绑定到 RectangleFSizeFPointFCGRectCGSizeCGPoint 的任何实例直接更改为原生类型 CGRectCGSizeCGPoint

例如,给定下述项的 Objective-C 初始值设定项:

- (id)initWithFrame:(CGRect)frame;

如果上一个绑定包含以下代码:

[Export ("initWithFrame:")]
IntPtr Constructor (RectangleF frame);

我们会将该代码更新为:

[Export ("initWithFrame:")]
IntPtr Constructor (CGRect frame);

现在所有代码更改都已到位,我们需要修改绑定项目或使文件绑定到 Unified API。

修改绑定项目

在更新绑定项目来使用 Unified API 的步骤中,最后我们需要修改用于生成项目的 MakeFile 或者 Xamarin 项目类型(如果我们从 Visual Studio for Mac 中进行绑定),并指示 btouch 绑定到 Unified API 而不是 Classic API。

更新生成文件

如果使用生成文件将绑定项目生成到 Xamarin .DLL,则需要包含 --new-style 命令行选项,并调用 btouch-native 而不是 btouch

因此,给定以下 MakeFile

BINDDIR=/src/binding
XBUILD=/Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild
PROJECT_ROOT=XMBindingLibrarySample
PROJECT=$(PROJECT_ROOT)/XMBindingLibrarySample.xcodeproj
TARGET=XMBindingLibrarySample
BTOUCH=/Developer/MonoTouch/usr/bin/btouch

all: XMBindingLibrary.dll

libXMBindingLibrarySample-i386.a:
	$(XBUILD) -project $(PROJECT) -target $(TARGET) -sdk iphonesimulator -configuration Release clean build
	-mv $(PROJECT_ROOT)/build/Release-iphonesimulator/lib$(TARGET).a $@

libXMBindingLibrarySample-arm64.a:
	$(XBUILD) -project $(PROJECT) -target $(TARGET) -sdk iphoneos -arch arm64 -configuration Release clean build
	-mv $(PROJECT_ROOT)/build/Release-iphoneos/lib$(TARGET).a $@

libXMBindingLibrarySample-armv7.a:
	$(XBUILD) -project $(PROJECT) -target $(TARGET) -sdk iphoneos -arch armv7 -configuration Release clean build
	-mv $(PROJECT_ROOT)/build/Release-iphoneos/lib$(TARGET).a $@

libXMBindingLibrarySampleUniversal.a: libXMBindingLibrarySample-armv7.a libXMBindingLibrarySample-i386.a libXMBindingLibrarySample-arm64.a
	lipo -create -output $@ $^

XMBindingLibrary.dll: AssemblyInfo.cs XMBindingLibrarySample.cs extras.cs libXMBindingLibrarySampleUniversal.a
	$(BTOUCH) -unsafe -out:$@ XMBindingLibrarySample.cs -x=AssemblyInfo.cs -x=extras.cs --link-with=libXMBindingLibrarySampleUniversal.a,libXMBindingLibrarySampleUniversal.a

clean:
	-rm -f *.a *.dll

我们需要从调用 btouch 切换到调用 btouch-native,因此我们将按如下所示调整宏定义:

BTOUCH=/Developer/MonoTouch/usr/bin/btouch-native

我们将更新对 btouch 的调用并添加 --new-style 选项,如下所示:

XMBindingLibrary.dll: AssemblyInfo.cs XMBindingLibrarySample.cs extras.cs libXMBindingLibrarySampleUniversal.a
	$(BTOUCH) -unsafe --new-style -out:$@ XMBindingLibrarySample.cs -x=AssemblyInfo.cs -x=extras.cs --link-with=libXMBindingLibrarySampleUniversal.a,libXMBindingLibrarySampleUniversal.a

现在,我们可以像平常一样执行 MakeFile 来生成新的 64 位版本的 API。

更新绑定项目类型

如果使用 Visual Studio for Mac 绑定项目模板来生成 API,需要更新到绑定项目模板新的 Unified API 版本。 执行此操作的最简单方法是启动新的 Unified API 绑定项目,并复制所有现有代码和设置。

请执行以下操作:

  1. 启动 Visual Studio for Mac。

  2. 选择“文件”>“新建”>“解决方案...”

  3. 在“新建解决方案”对话框中,选择“iOS”>“Unified API”>“iOS 绑定项目”:

    在“新建解决方案”对话框中,选择“iOS”/“Unified API”/“iOS 绑定项目”

  4. 在“配置新项目”对话框中,输入新绑定项目的名称,然后单击“确定”按钮。

  5. 添加要为其创建绑定的 Objective-C 库的 64 位版本。

  6. 从现有 32 位 Classic API 绑定项目复制源代码(如 ApiDefinition.csStructsAndEnums.cs 文件)。

  7. 对源代码文件进行上述更改。

完成所有这些更改后,可以像生成 32 位版本一样生成新的 64 位版本的 API。

总结

在本文中,我们介绍了需要对现有 Xamarin 绑定项目进行哪些更改来支持新的 Unified API 和 64 位设备,还介绍了生成新的 64 位兼容 API 版本所需的步骤。