通过 Xamarin Unified API Mac 和 iOS 之间共享代码,并支持使用同一二进制文件的 32 位和 64 位应用程序。 默认情况下Unified API Xamarin.iOS 和 Xamarin.Mac 项目中使用此配置。
Xamarin Classic API之前,Unified API已弃用。
支持 Xamarin.iOS Classic API (monotouch.dll) 版本是 Xamarin.iOS 9.10。
Xamarin.Mac 仍Classic API,但不再更新。 由于已弃用,开发人员应将其应用程序移到Unified API。
更新Classic API应用
按照平台的相关说明操作:
更新现有应用
更新现有 iOS 应用
更新现有 Mac 应用
更新现有 Xamarin.Forms 应用
将绑定迁移到 Unified API
无论迁移哪些应用程序,请查看这些提示,以帮助你
成功更新Unified API。
从此之后,我们的 API 将以两种方式出现:
Classic API:
限制为 32 位 (在) 和 程序集中
monotouch.dll
公开
XamMac.dll
。
Unified API:
使用 和 程序集中提供的单个 API
Xamarin.iOS.dll
同时支持 32 位和 64 位
Xamarin.Mac.dll
开发。
这意味着,对于Enterprise开发人员 (面向 App Store) ,可以继续使用现有的经典 API,因为我们会永久维护它们,也可以升级到新的 API。
命名空间更改
为了减少 Mac 和 iOS 产品之间共享代码的摩擦,我们正在更改产品中 API 的命名空间。
我们将从 iOS 产品删除前缀"MonoTouch",在数据类型上从 Mac 产品删除"MonoMac"。
这样,无需使用条件编译即可在 Mac 和 iOS 平台之间共享代码更加简单,并减少源代码文件顶部的干扰。
Classic API:
命名空间使用
MonoTouch.
或
MonoMac.
前缀。
Unified API:
无命名空间前缀
运行时默认值
默认情况下Unified API使用
SGen
垃圾回收器和新的引用
计数
系统跟踪对象所有权。 此功能已移植到 Xamarin.Mac。
这解决了开发人员面临旧系统时面临的许多问题,并简化
内存管理
。
请注意,即使为 Classic API,也能够启用"新建 Refcount",但默认值是Classic API,并且不需要用户做出任何更改。 借助Unified API,我们利用更改默认值的机会为开发人员提供在重构和重新测试代码的同时进行的所有改进。
API 更改
该Unified API删除了不推荐使用的方法,并且存在一些实例,当 API 名称绑定到经典 API 中的原始 MonoTouch 和 MonoMac 命名空间时,API 名称中会存在拼写错误。 这些实例已在新的统一 API 中更正,需要在组件、iOS 和 Mac 应用程序中进行更新。 下面是可能遇到最常见的问题的列表:
Classic API方法名称
Unified 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
有关从经典部署切换到 Unified API 时更改的完整列表,请参阅经典
(monotouch.dll) 与统一 (Xamarin.iOS.dll) API 差异
文档。
更新到统一
统
一 API 中
未提供多个经典中的旧/
损坏/已弃用 API。 在启动
CS0616
(手动或自动)
[Obsolete]
升级之前,可以更轻松地修复警告,因为将在警告 (的一部分) 将指导你使用正确的 API。
请注意,我们将发布
经典
API 更改与统一 API 更改的差异,这些更改可以在项目更新之前或之后使用。 在经典中仍然修复过时的调用通常可以节省时间 (减少文档查找) 。
按照这些说明
将现有 iOS 应用
或
Mac 应用更新
到Unified API。
请查看本页的其余部分,并
查看这些提示
,获取有关迁移代码的其他信息。
NuGet
NuGet以前支持 Xamarin.iOS 的包Classic API
Monotouch10
平台名字对象发布其程序集。
该Unified API引入了兼容包的新平台标识符 -
Xamarin.iOS10
。 现有NuGet包需要更新,以添加对此平台的支持,只需根据Unified API。
如果在同一 Xamarin.iOS 项目中出现"错误 3 不能同时包含'monotouch.dll'和'Xamarin.iOS.dll'"格式的错误 - 显式引用了"Xamarin.iOS.dll", 虽然将应用程序转换为统一 API 后,"
xxx, Version=0.0.000, Culture=neutral, PublicKeyToken=null"
引用了"monotouch.dll",但通常是由于项目中有一个组件或 NuGet 包,而该项目尚未更新到 Unified API。 需要删除现有组件/NuGet更新到支持统一 API 的版本,并执行干净生成。
64 位道路
有关支持 32 位和 64 位应用程序的背景信息以及框架信息,请参阅 32 位和
64 位平台注意事项
。
新数据类型
在差异的核心,Mac 和 iOS API 都使用特定于体系结构的数据类型,这些数据类型在 32 位平台上始终为 32 位,在 64 位平台上始终为 64 位。
例如, Objective-C 在
NSInteger
32 位系统上
int32_t
将数据类型映射到
int64_t
,在 64 位系统上映射到 。
为了匹配此
int
行为,Unified API,我们将替换以前使用的 (在 .NET
System.Int32
中定义为始终) 新数据类型:
System.nint
。 可以将"n"视为"本机"的含义,因此平台的本机整数类型。
我们将引入
nint
,
nuint
并
nfloat
在必要时提供基于它们构建的数据类型。
若要详细了解这些数据类型更改,请参阅
本机类型
文档。
如何检测 iOS 应用的体系结构
在某些情况下,应用程序需要知道它是在 32 位还是 64 位 iOS 系统中运行。 以下代码可用于检查体系结构:
if (IntPtr.Size == 4) {
Console.WriteLine ("32-bit App");
} else if (IntPtr.Size == 8) {
Console.WriteLine ("64-bit App");
数组和 System.Collections.Generic
由于 C# 索引器int
nint
int
需要类型 为 ,因此必须显式将值强制转换到 ,以访问集合或数组中的元素。 例如: 。
public List<string> Names = new List<string>();
public string GetName(nint index) {
return Names[(int)index];
这是预期行为,因为int
nint
从 到 的转换在 64 位上是丢失的,所以不执行隐式转换。
将 DateTime 转换为 NSDate
使用统一 API 时,不再执行 到DateTime
NSDate
值的隐式转换。 这些值需要从一种类型显式转换为另一种类型。 以下扩展方法可用于自动执行此过程:
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 取代。 如果Classic API旧版 iOS (,则仍然可以使用此) 。
此类 API (和 [Obsolete]
属性) 包含在新的 Xamarin.iOS 程序集中。
API 不正确 某些 API 的名称有拼写错误。
对于原始程序集(monotouch.dll 和 XamMac.dll) ,我们保留了旧代码的兼容性,但它们已从 Unified 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 和统一 API 中提供。
请注意, .ctor(NSObjectFlag)
现在也是 , protected
但此子类外很少使用。
NSAction 替换为 Action
使用统一 API 时, NSAction
已删除 ,以支持标准 .NET Action
。 这是一项重大改进,因为 Action
是一种常见的 .NET 类型 NSAction
,而 特定于 Xamarin.iOS。 它们执行完全相同的事情,但它们是不同的和不兼容的类型,导致必须编写更多代码才能获得相同的结果。
例如,如果现有的 Xamarin 应用程序包含以下代码:
UITapGestureRecognizer singleTap = new UITapGestureRecognizer (new NSAction (delegate() {
ShowDropDownAnimated (tblDataView);
现在可以使用简单的 lambda 替换它:
UITapGestureRecognizer singleTap = new UITapGestureRecognizer (() => ShowDropDownAnimated(tblDataView));
以前,由于 Action
无法分配给 NSAction
,将导致编译器错误,但由于 UITapGestureRecognizer
现在使用 Action
而不 NSAction
是,它在统一 api 中是有效的。
自定义委托替换为操作 < T>
在 统一 的一些简单 (例如,将 .net 委托) 一个参数替换为 Action<T>
。 例如
public delegate void NSNotificationHandler (NSNotification notification);
现在 Action<NSNotification>
可用作。 这会在 Xamarin 和你自己的应用程序中提高代码重用性并减少代码重复。
任务 < bool > 已替换为 task < Boolean,NSError>>
在 经典 中,有一些返回 Task<bool>
的异步 api。 但是,其中的某些在是签名的一部分时 NSError
使用,即 bool
已存在 true
,你必须捕获异常才能获取 NSError
。
由于有些错误很常见,并且返回值无效,此模式在 统一 中更改为返回 Task<Tuple<Boolean,NSError>>
。 这使你可以检查成功和异步调用期间可能发生的任何错误。
NSString vs string
在少数情况下,某些常量必须从 string
更改为 NSString
,例如 UITableViewCell
public virtual string ReuseIdentifier { get; }
public virtual NSString ReuseIdentifier { get; }
通常,我们更喜欢 .NET System.String
类型。 不过,尽管有 Apple 准则,但某些本机 API 却比较常量指针 (不是字符串本身) 并且这仅在我们将常数公开为 NSString
时才起作用。
Objective-C 通讯
原始 Monotouch.dialog 未对 ObjC 协议提供完全支持,并且添加了一些非最佳的 API,以支持最常见的方案。 此限制并不存在,但为了向后兼容,多个 Api 将保留在和 XamMac.dll
内 monotouch.dll
。
这些限制已在统一 Api 上删除并清除。 大多数更改将如下所示:
public virtual AVAssetResourceLoaderDelegate Delegate { get; }
public virtual IAVAssetResourceLoaderDelegate Delegate { get; }
I
前缀表示统一公开接口,而不是 ObjC 协议的特定类型。 这样就可以轻松地不希望为 Xamarin 提供的特定类型划分子类。
它还允许更精确、更易于使用的 API,例如:
public virtual void SelectionDidChange (NSObject uiTextInput);
public virtual void SelectionDidChange (IUITextInput uiTextInput);
此类 API 现在更易于我们,无需参考文档,IDE 代码完成将为你提供基于协议/接口的更多有用建议。
NSCoding 协议
我们的原始绑定包含每个类型的 .ctor (NSCoder) ,即使它不支持 NSCoding
协议。 中存在一个 Encode(NSCoder)
用于对对象进行编码的 NSObject
方法。
但仅当实例与 NSCoding 协议相符时,此方法才起作用。
在 Unified API 修复了此项。 如果类型符合 NSCoding
,则新的程序集将仅具有 .ctor(NSCoder)
。 此外,此类类型现在具有一个 Encode(NSCoder)
符合 INSCoding
接口的方法。
低影响:在大多数情况下,此更改不会影响应用程序,因为旧的、删除的构造函数无法使用。
进一步使用技巧
要注意的其他更改会在将 应用程序更新到 Unified API 的提示中列出。
更新 iOS 应用程序
更新 Mac 应用
更新 Xamarin 应用程序
更新使用技巧
经典与 Unified API 差异
使用跨平台应用中的本机类型