共用方式為


整合 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」 視為「原生」,因此平臺的原生整數類型。

我們引進 nintnuintnfloat 在必要時提供建置在它們之上的數據類型。

若要深入瞭解這些數據類型變更,請參閱 原生類型 檔。

如何偵測 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];
}

這是預期的行為,因為從 intnint 的轉換在64位上遺失,因此不會進行隱含轉換。

將 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 已取代為 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 的秘訣中