整合 API 概觀
Xamarin 的整合 API 可讓您在 Mac 與 iOS 之間共用程式代碼,並支援具有相同二進位檔的 32 和 64 位應用程式。 新的 Xamarin.iOS 和 Xamarin.Mac 項目預設會使用整合 API。
重要
Xamarin 傳統 API 之前統一 API 已被取代。
- 支援傳統 API 的最後一個版本 Xamarin.iOS (monotouch.dll) 是 Xamarin.iOS 9.10。
- Xamarin.Mac 仍然支持傳統 API,但不再更新。 由於它已被取代,開發人員應該將其應用程式移至整合API。
更新傳統 API 型應用程式
請遵循平台的相關指示:
將程式碼更新至 Unified API 的祕訣
無論您要移轉的應用程式為何,請查看 這些秘訣 ,以協助您成功更新至整合 API。
連結庫分割
從此開始,我們的 API 會以兩種方式呈現:
- 傳統 API:限制為 32 位(僅限),並公開在和
XamMac.dll
元件中monotouch.dll
。 - 整合 API:使用 和
Xamarin.Mac.dll
元件中Xamarin.iOS.dll
可用的單一 API 支援 32 和 64 位開發。
這表示對於企業開發人員(而不是以 App Store 為目標),您可以繼續使用現有的傳統 API,因為我們會永遠維護它們,或者您可以升級至新的 API。
命名空間變更
為了減少在 Mac 和 iOS 產品之間共用程式碼的摩擦,我們正在變更產品中 API 的命名空間。
我們會從 iOS 產品卸除前置詞 「MonoTouch」 並在數據類型上從 Mac 產品卸除 「MonoMac」。
這可讓您更輕鬆地在 Mac 和 iOS 平台之間共用程式代碼,而不需訴諸條件式編譯,並減少原始程式碼檔案頂端的雜訊。
- 傳統 API: 命名空間使用
MonoTouch.
或MonoMac.
前置詞。 - 整合 API: 沒有命名空間前置詞
運行時間預設值
統一 API 預設會使用 SGen 垃圾收集行程和 新的參考計數 系統來追蹤物件擁有權。 這項相同的功能已移植到 Xamarin.Mac。
這解決了開發人員面對舊系統並簡化 記憶體管理的問題。
請注意,即使針對傳統 API 啟用 New Refcount 也可行,但預設值是保守的,而且不需要使用者進行任何變更。 透過整合 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) 與 Unified (Xamarin.iOS.dll) API 差異 檔。
更新至 Unified
在傳統 API 中無法使用數個舊/中斷/已取代的 API。 啟動您的 (手動或自動化) 升級之前,可以更輕鬆地修正 CS0616
警告,因為您將擁有 [Obsolete]
屬性訊息(警告的一部分)來引導您前往正確的 API。
請注意,我們正在發佈傳統與統一 API 變更的差異 ,這些變更可在專案更新之前或之後使用。 在傳統中仍修正過時的呼叫通常是省時時間(文件查閱較少)。
請遵循這些指示,將現有的 iOS 應用程式或 Mac 應用程式更新為整合 API。 檢閱此頁面的其餘部分,以及 這些秘訣 ,以取得移轉程式代碼的其他資訊。
NuGet (英文)
先前透過傳統 API 支援 Xamarin.iOS 的 NuGet 套件會使用 Monotouch10 平臺 Moniker 發佈其元件。
整合 API 引進了相容套件的新平台識別碼 - Xamarin.iOS10。 您必須更新現有的 NuGet 套件,才能根據整合 API 建置來新增此平台的支援。
重要
如果您在相同的 Xamarin.iOS 專案中出現 錯誤「錯誤 3 無法同時包含 『monotouch.dll』 和 'Xamarin.iOS.dll' - 明確參考 'Xamarin.iOS.dll', 雖然 'monotouch.dll' 是由 'xxx, Version=0.0.000, Culture=neutral, PublicKeyToken=null'' 在將您的應用程式轉換成 Unified API 之後參考,但通常是因為專案中有一個元件或 NuGet 套件尚未更新為 Unified API。 您必須移除現有的元件/NuGet、更新為支援整合 API 的版本,並執行全新組建。
通往 64 位的道路
如需支援 32 和 64 位應用程式的背景資訊,以及架構的相關信息,請參閱 32 和 64 位平台考慮。
新資料類型
在差異的核心,Mac 和 iOS API 都使用架構特定的數據類型,在 32 位平臺上一律是 32 位,在 64 位平臺上是 64 位。
例如, Objective-C 將 NSInteger
資料類型對應至 int32_t
32 位系統上和 int64_t
64 位系統上的 。
為了符合此行為,在整合 API 上,我們會將先前的用法 int
取代為新的數據類型,其中在 .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 取代。 傳統 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 已取代為 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.iOS 和您自己的應用程式內的程式碼重複。
工作<布爾> 值,NSError 取代為任務<布爾值>>
在傳統中,有一些異步 API 傳Task<bool>
回 。 不過,其中有些是在 簽章的一部分時 NSError
使用,也就是 bool
已經, true
而且您必須攔截例外狀況,才能取得 NSError
。
由於某些錯誤非常常見,而且傳回值並不適用於此模式,因此此模式已變更為統一Task<Tuple<Boolean,NSError>>
以傳回 。 這可讓您檢查異步呼叫期間可能發生的成功和任何錯誤。
NSString 與字串
在某些情況下,某些常數必須從 string
變更為 NSString
,例如 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
協定也一樣。 中NSObject
存在單Encode(NSCoder)
一方法來編碼 物件。
但只有在實例符合 NSCoding 通訊協定時,這個方法才能運作。
在整合 API 上,我們已修正此問題。 只有在型別符合 NSCoding
時,新的元件才會有 .ctor(NSCoder)
。 此外,這類類型現在也有符合 Encode(NSCoder)
INSCoding
介面的方法。
低影響:在大部分情況下,這項變更不會影響應用程式,因為舊的、已移除的建構函式無法使用。
進一步 提示
要注意的其他變更會列在將應用程式更新至整合 API 的秘訣中。