Xamarin iOS API 設計

文章推薦指數: 80 %
投票人數:10人

如果您的類型需要執行決定性的完成,請覆寫NSObject (bool) 方法。

dispose 的參數會是「bool 處置」,如果設定為true,則表示因為使用者明確呼叫了物件上 ... 跳到主要內容 已不再支援此瀏覽器。

請升級至MicrosoftEdge,以利用最新功能、安全性更新和技術支援。

下載MicrosoftEdge 其他資訊 目錄 結束焦點模式 閱讀英文 儲存 目錄 閱讀英文 儲存 Twitter LinkedIn Facebook 電子郵件 目錄 XamariniOSAPI設計 發行項 08/10/2022 7位參與者 本文內容 除了屬於Mono的核心基類庫之外,Xamarin還隨附各種iOSapi的系結,可讓開發人員使用Mono建立原生iOS應用程式。

在Xamarin的核心中,有一個interop引擎可橋接全球c#世界Objective-C,以及IOSC型api(例如CoreGraphics和OpenGLES)的系結。

要與Objective-C程式碼通訊的低層級執行時間位於Monotouch.dll.ObjCRuntime。

此外,也會提供Foundation、CoreFoundation和UIKit的系結。

設計原則 本節將詳細說明一些適用于Xamarin的設計原則(它們也適用于Xamarin,也就是macOS上的MonoObjective-C系結): 遵循架構設計指導方針 允許開發人員Objective-C提供子類別類別: 衍生自現有類別 呼叫基底函式以進行鏈 覆寫方法應該使用c#的覆寫系統來完成 子類別化應該搭配c#標準結構使用 不要將開發人員公開給Objective-C選取器 提供可呼叫任意Objective-C程式庫的機制 讓一般Objective-C工作更容易且更難Objective-C進行 將屬性公開Objective-C為c#屬性 公開強型別API: 提高型別安全 將執行階段錯誤降至最低 在傳回類型上取得IDEIntelliSense 允許IDE快顯視窗檔 鼓勵以IDE探索Api: 例如,您不會公開弱型別陣列,如下所示: NSArray*getViews 公開強型別,如下所示: NSView[]Views{get;set;} 使用強型別可讓VisualStudioforMac在流覽API時執行自動完成的功能,讓所有的作業都System.Array可在傳回的值上使用,並允許傳回值參與LINQ。

原生c#類型: NSString成為string intuint應該已經列舉為c#列舉的參數和具有[Flags]屬性的c#列舉 不是型別中立NSArray的物件,而是將陣列公開為強型別陣列。

針對事件和通知,讓使用者選擇: 預設為強型別版本 適用于先進使用案例的弱類型版本 Objective-C支援委派模式: C#事件系統 公開c#委派(lambda、匿名方法,以及System.Delegate將Objective-Capi)為區塊 組件 Xamarin包含許多構成XamarinIOS設定檔的元件。

[元件]頁面有詳細資訊。

主要命名空間 ObjCRuntime ObjCRuntime命名空間可讓開發人員在c#與Objective-C之間橋接世界。

這是根據Cocoa#和Gtk#的體驗,特別針對iOS設計的新系結。

Foundation 基礎命名空間提供的基本資料類型,是為了與Objective-C屬於iOS一部分的基礎架構交互操作,而且是中Objective-C物件導向程式設計的基礎。

Xamarin:c#中的類別Objective-C階層架構。

例如,Objective-C您可以從c#透過NSObject使用基類NSObject。

雖然Foundation命名空間提供基礎Objective-C基礎類型的系結,但在少數情況下,我們已將基礎類型對應至.net類型。

例如: 執行時間不會處理NSString和NSArray,而是會將它們公開為API中的c#字串和強型別陣列。

這裡公開各種協助程式Api,可讓開發人員系結目前未受Xamarin所系結的協力廠商Objective-Capi、其他IOSapi或api。

FormoreinformationonbindingAPIs,seetheXamarin.iOSBindingGeneratorsection. NSObject NSObject型別是所有Objective-C系結的基礎。

Xamarin類型會從iOSCocoaTouchApi鏡像兩種類型的類別:C類型(通常稱為CoreFoundation類型)以及所有衍生自NSObject類別)的Objective-C類型(。

針對每個鏡像非受控型別的型別,都可以透過Handle屬性取得原生物件。

雖然Mono將提供所有物件的垃圾收集,Foundation.NSObject但會實IDisposable介面。

您可以明確釋放任何指定NSObject的資源,而不必等待垃圾收集行程開始進行。

當您使用繁重的NSObjects(例如,可能持有大型資料區塊指標的UIImages)時,明確釋放資源相當重要。

如果您的類型需要執行決定性的完成,請覆寫NSObject(bool)方法。

dispose的參數會是「bool處置」,如果設定為true,則表示因為使用者明確呼叫了物件上的dispose(),所以會呼叫dispose方法。

False值表示您的Dispose(bool處置)方法是從完成項執行緒上的完成項呼叫。

類別 從Xamarin.iOS8.10開始,可以從c#建立Objective-C類別。

這是使用Category屬性來完成,指定要擴充為屬性之引數的型別。

下列範例會擴充NSString。

[Category(typeof(NSString))] 每個類別方法都使用一般機制來匯出方法以Objective-C使用Export屬性: [Export("today")] publicstaticstringToday() { return"Today"; } 所有managed擴充方法都必須是靜態的,但您可以使用c#中的擴充方法標準語法來建立Objective-C實例方法: [Export("toUpper")] publicstaticstringToUpper(thisNSStringself) { returnself.ToString().ToUpper(); } 擴充方法的第一個引數將是叫用方法的實例。

完整範例: [Category(typeof(NSString))] publicstaticclassMyStringCategory { [Export("toUpper")] staticstringToUpper(thisNSStringself) { returnself.ToString().ToUpper(); } } 這個範例會將原生toUpper實例方法加入至NSString類別,而這個類別可從叫用Objective-C。

[Category(typeof(UIViewController))] publicstaticclassMyViewControllerCategory { [Export("shouldAutoRotate")] staticboolGlobalRotate() { returntrue; } } 其中一個實用的案例是將方法新增至程式碼基底中的整個類別集合,例如,這會讓所有UIViewController實例報告可以旋轉: [Category(typeof(UINavigationController))] classRotation_IOS6{ [Export("shouldAutorotate:")] staticboolShouldAutoRotate(thisUINavigationControllerself) { returntrue; } } PreserveAttribute PreserveAttribute是一個自訂屬性,用來在處理應用程式以縮減其大小時,用來指示mtouch(即)在階段中保留類型或成員類型的成員。

未由應用程式以靜態方式連結的每個成員都可能會移除。

因此,這個屬性會用來標記未以靜態方式參考的成員,但您的應用程式仍需要此屬性。

例如,若您是以動態方式來具現化類型,您可以保留您類型的預設建構函式。

若您使用的是XML序列化,則您可能會想要保留您類型的屬性。

您可以將此屬性套用到某個類型的每個成員,或是套用到類型本身。

如果您想要保留整個類型,可以在類型上使用[保留(AllMembers=true)]語法。

UIKit UIKit命名空間包含以c#類別形式組成CocoaTouch的所有UI元件的一對一對應。

API已修改為遵循c#語言中使用的慣例。

C#委派提供給一般作業。

如需詳細資訊,請參閱委派一節。

OpenGLES 針對OpenGLES,我們會將修改過的opentk簡介API版本(物件導向系結)散發至已修改為使用CoreGraphics資料類型和結構的OpenGL,並只公開iOS上可用的功能。

OpenGLES1.1功能可透過ES11.GL類型使用。

OpenGLES2.0功能可透過ES20.GL類型使用。

OpenGLES3.0功能可透過ES30.GL類型使用。

系結設計 Xamarin不只是基礎Objective-C平臺的系結。

它會擴充.NET型別系統並分派系統,以更妥善地blendc#和Objective-C。

就像P/Invoke是在Windows和Linux上叫用原生程式庫的公用程式,或可在Windows的COMinterop上使用IJW支援一樣,Xamarin也擴充了執行時間,以支援將c#物件系結至Objective-C物件。

在接下來的幾節中,您不需要針對建立XamariniOS應用程式的使用者進行討論,但可協助開發人員瞭解完成專案的方式,並在建立更複雜的應用程式時協助他們。

類型 無論是哪種情況,c#型別都會公開給c#universe,而非低層級的基礎類型。

這表示API會使用c#"string"類型而不是NSString,而且它會使用強型別的c#陣列,而不是公開NSArray。

一般而言,在Xamarin和Xamarin的設計中,不會公開基礎NSArray物件。

相反地,執行時間會自動將s轉換NSArray成某個NSObject類別的強型別陣列。

因此,Xamarin不會公開弱型別方法(例如GetViews)來傳回NSArray: NSArrayGetViews(); 相反地,系結會公開強型別傳回值,如下所示: UIView[]GetViews(); 有幾個方法會在中NSArray公開,在您可能想要直接使用NSArray的角落案例中,但不建議在API系結中使用它們。

此外,在ClassicAPI而不是在CoreGraphicsAPI公開CGRect、CGPointCGSize和以外,我們會將它們PointFSystem.DrawingRectangleF取代為實作為和,並且SizeF可協助開發人員保留使用opentk簡介的現有OpenGL程式碼。

使用新的64位UnifiedAPI時,應使用CoreGraphicsAPI。

繼承 XamarinAPI設計可讓開發人員以其擴充c#類型的相同方式來擴充原生Objective-C類型,使用衍生類別上的"override"關鍵字,並使用"base"c#關鍵字連結到基底實作為基底。

這項設計可讓開發人員避免在其開發過程中處理Objective-C選取器,因為整個Objective-C系統已經包裝在Xamarin.iOS程式庫中。

類型和InterfaceBuilder 當您建立的.NET類別是InterfaceBuilder所建立之型別的實例時,您需要提供採用單一IntPtr參數的函式。

這是將managed物件實例系結至非受控物件的必要項。

程式碼是由一行組成,如下所示: publicpartialclassvoidMyView:UIView{ //Thisistheconstructorthatyouneedtoadd. publicMyView(IntPtrhandle):base(handle){} } 委派 Objective-C和c#對於每種語言的單字委派都有不同的意義。

Objective-C在世界中,以及您可以在線上找到CocoaTouch的檔中,委派通常是將回應一組方法的類別實例。

這類似于c#介面,差別在於方法不一定是強制性的。

這些委派在UIKit和其他CocoaTouchApi中扮演著重要的角色。

它們可用來完成各種工作: 若要為您的程式碼提供通知(類似于c#或Gtk+)中的事件傳遞。

為數據視覺效果控制項執行模型。

來驅動控制項的行為。

程式設計模式的設計目的是要將衍生類別的建立最小化,以改變控制項的行為。

這個解決方案與其他GUI工具組在多年來完成的精神類似:Gtk的信號、Qt位置、Winforms事件、WPF/Silverlight事件等等。

為了避免有數百個介面(每個動作都有一個)或要求開發人員執行不需要的許多方法,Objective-C支援選擇性的方法定義。

這與需要執行所有方法的c#介面不同。

在[類別]中Objective-C,您會看到使用此程式設計模式的類別會公開一個稱為delegate的屬性,此屬性是必要的,以執行介面的必要部分以及零或多個選擇性部分。

在Xamarin中,提供三種互斥機制來系結至這些委派: Via事件。

透過屬性的Delegate強型別 透過屬性的WeakDelegate鬆散類型 例如,請考慮UIWebView類別。

這會分派給指派給委派屬性的UIWebViewDelegate實例。

Via事件 針對許多類型,Xamarin會自動建立適當的委派,以將呼叫轉送UIWebViewDelegate至c#事件。

針對UIWebView: WebViewDidStartLoad方法會對應至UIWebView.LoadStarted事件。

WebViewDidFinishLoad方法會對應至UIWebView.LoadFinished事件。

Web程式:didFailLoadWithError方法會對應至UIWebView.LoadError事件。

例如,這個簡單的程式會記錄載入網頁視圖時的開始和結束時間: DateTimestartTime,endTime; varweb=newUIWebView(newCGRect(0,0,200,200)); web.LoadStarted+=(o,e)=>startTime=DateTime.Now; web.LoadFinished+=(o,e)=>endTime=DateTime.Now; Via屬性 當事件可能有一個以上的訂閱者時,事件會很有用。

此外,事件僅限於程式碼沒有傳回值的情況。

在程式碼預期會傳回值的情況下,我們選擇改為屬性。

這表示在指定的時間內,只有一個方法可以設定為物件。

例如,您可以使用這種機制來關閉的處理常式UITextField上螢幕上的鍵盤: voidSetupTextField(UITextFieldtf) { tf.ShouldReturn=delegate(textfield){ textfield.ResignFirstResponder(); returntrue; } } 在此情況下,UITextField的ShouldReturn屬性會將傳回bool值的委派當作引數,並決定是否應該在按下[返回]按鈕時,進行某些動作。

在我們的方法中,我們會將true傳回給呼叫者,但我們也會從螢幕中移除鍵盤(當欄位呼叫ResignFirstResponder)時,就會發生這種情況。

透過委派屬性的強型別 如果您不想使用事件,您可以提供自己的UIWebViewDelegate子類別,並將它指派給UIWebView。

Delegate屬性。

一旦UIWebView之後,UIWebView事件分派機制將無法再運作,而且會在對應的事件發生時叫用UIWebViewDelegate方法。

例如,這種簡單類型會記錄載入webview所花費的時間: classNotifier:UIWebViewDelegate{ DateTimestartTime,endTime; publicoverrideLoadStarted(UIWebViewwebview) { startTime=DateTime.Now; } publicoverrideLoadingFinished(UIWebViewwebView) { endTime=DateTime.Now; } } 上述程式碼中使用的程式碼如下所示: varweb=newUIWebView(newCGRect(0,0,200,200)); web.Delegate=newNotifier(); 上述程式會建立UIWebViewer,並指示它將訊息傳送給通知者的實例,這是我們為了回應訊息而建立的類別。

這個模式也可用來控制特定控制項的行為,例如在UIWebView案例中,UIWebViewShouldStartLoad屬性允許UIWebView實例控制是否UIWebView要載入頁面。

此模式也可用來提供一些控制項的隨選資料。

例如,iosuitableview範例控制項是功能強大的資料表轉譯控制項,而且外觀和內容都是由UITableViewDataSource的實例所驅動。

透過WeakDelegate屬性的鬆散類型 除了強型別屬性之外,還有一個弱式型別委派,可讓開發人員在需要時,以不同的方式系結專案。

在所有的強Delegate型別屬性都在Xamarin的系結中公開時,也會公開對應WeakDelegate的屬性。

使用WeakDelegate時,您必須負責使用Export屬性來指定選取器,以正確裝飾您的類別。

例如: classNotifier:NSObject{ DateTimestartTime,endTime; [Export("webViewDidStartLoad:")] publicvoidLoadStarted(UIWebViewwebview) { startTime=DateTime.Now; } [Export("webViewDidFinishLoad:")] publicvoidLoadingFinished(UIWebViewwebView) { endTime=DateTime.Now; } } [...] varweb=newUIWebView(newCGRect(0,0,200,200)); web.WeakDelegate=newNotifier(); WeakDelegate一旦指派屬性,Delegate就不會使用屬性。

此外,如果您在想要[匯出]的繼承基類中執行方法,就必須將它設為公用方法。

Objective-C委派模式與C的對應# 當您看到Objective-C如下所示的範例: foo.delegate=[[SomethingDelegate]alloc]init] 這會指示語言建立並建立類別"SomethingDelegate"的實例,並將值指派給foo變數上的委派屬性。

這項機制受到Xamarin和c#的支援,語法如下: foo.Delegate=newSomethingDelegate(); 在Xamarin中,我們提供了對應至Objective-C委派類別的強型別類別。

若要使用它們,您將會子類別化並覆寫由Xamarin的實作為定義的方法。

如需其運作方式的詳細資訊,請參閱下面的「模型」一節。

將委派對應到C# UIKit一般會使用Objective-C兩種形式的委派。

第一個表單會提供元件模型的介面。

例如,做為可依需求提供資料的機制,例如清單視圖的資料儲存設備。

在這些情況下,您應該一律建立適當類別的實例,並指派變數。

在下列範例中,我們會為使用字串的模型提供UIPickerView一個實作為: publicclassSampleTitleModel:UIPickerViewTitleModel{ publicoverridestringTitleForRow(UIPickerViewpicker,nintrow,nintcomponent) { returnString.Format("At{0}{1}",row,component); } } [...] pickerView.Model=newMyPickerModel(); 第二種形式是提供事件的通知。

在這些情況下,雖然我們仍會以上述形式公開API,但我們也會提供c#事件,這應該更容易用於快速作業,並與c#中的匿名委派和lambda運算式整合。

例如,您可以訂閱UIAccelerometer事件: UIAccelerometer.SharedAccelerometer.Acceleration+=(sender,args)=>{ UIAccelerationacc=args.Acceleration; Console.WriteLine("Time={0}at{1},{2},{3}",acc.Time,acc.X,acc.Y,acc.Z); } 有兩個選項可供使用,但以程式設計人員而言,您必須挑選一個。

如果您建立自己的強型別回應程式/委派實例,並將它指派給它,則c#事件將無法運作。

如果您使用c#事件,將永遠不會呼叫回應者/委派類別中的方法。

先前使用UIWebView的範例可以使用c#3.0lambda來撰寫,如下所示: varweb=newUIWebView(newCGRect(0,0,200,200)); web.LoadStarted+=()=>{startTime=DateTime.Now;} web.LoadFinished+=()=>{endTime=DateTime.Now;} 回應事件 在程式碼中Objective-C,有時多個控制項的多個控制項和提供者的事件處理常式會裝載在相同的類別中。

這是可能的,因為類別會回應訊息,而且只要類別回應訊息,就可以將物件連結在一起。

如先前所述,Xamarin支援以c#事件為基礎的程式設計模型和Objective-C委派模式,您可以在其中建立新的類別來執行委派,並覆寫所需的方法。

也可以支援Objective-C的模式,其中多個不同作業的回應程式都裝載在相同類別的實例中。

若要這樣做,您必須使用適用于Xamarin系結的低層級功能。

例如,如果您想要讓類別在相同類別的實例中同時UITextFieldDelegate.textFieldShouldClear回應:訊息和UIWebViewDelegate.webViewDidStartLoad:,您必須使用[匯出]屬性聲明: publicclassMyCallbacks:NSObject{ [Export("textFieldShouldClear:"] publicboolshould_we_clear(UITextFieldtf) { returntrue; } [Export("webViewDidStartLoad:")] publicvoidOnWebViewStart(UIWebViewview) { Console.WriteLine("Loadingstarted"); } } 方法的c#名稱並不重要;重要的是傳遞至[Export]屬性的字串。

使用這種程式設計樣式時,請確定c#參數符合執行時間引擎將傳遞的實際類型。

模型 在UIKit儲存設施中,或在使用helper類別所執行的回應程式中,這些會在程式碼中Objective-C參考為委派,並實作為通訊協定。

Objective-C通訊協定就像介面,但它們支援選擇性方法,也就是,並非所有的方法都必須執行,才能讓通訊協定運作。

有兩種方式可執行模型。

您可以手動執行,或使用現有的強型別定義。

當您嘗試執行由Xamarin未系結的類別時,需要手動機制。

做法很簡單: 以旗標標示類別以註冊執行時間 在您想要覆寫的每個方法上,套用[Export]屬性與實際的選取器名稱 具現化類別,並將它傳遞。

例如,下列程式只會執行Uiapplicationdelegate以便通訊協定定義中的其中一個選擇性方法: publicclassMyAppController:NSObject{ [Export("applicationDidFinishLaunching:")] publicvoidFinishedLaunching(UIApplicationapp) { SetupWindow(); } } Objective-C選取器名稱("applicationDidFinishLaunching:")是使用Export屬性來宣告,而類別是以屬性([Register]attribute)註冊。

Xamarin提供強型別宣告,可供使用,且不需要手動系結。

為了支援此程式設計模型,Xamarin執行時間支援類別宣告上的[Model]屬性。

這會告知執行時間,除非明確地執行方法,否則它不應該連接類別中的所有方法。

這表示在UIKit中,以選擇性方法表示通訊協定的類別會以如下方式撰寫: [Model] publicclassSomeViewModel:NSObject{ [Export("someMethod:")] publicvirtualintSomeMethod(TheViewview){ thrownewModelNotImplementedException(); } ... } 當您想要執行僅執行某些方法的模型時,您只需要覆寫您感興趣的方法,並忽略其他方法。

執行時間只會連接覆寫的方法,而不會連結到Objective-C世界的原始方法。

相當於先前的手動範例: publicclassAppController:UIApplicationDelegate{ publicoverridevoidFinishedLaunching(UIApplicationuia) { ... } } 優點是不需要深入Objective-C探索標頭檔以尋找選取器、引數的類型或c#的對應,以及您從VisualStudioforMac取得intellisense以及強式類型 XIB輸出口和C# 這是使用c#與c#整合的低層級描述,並為適用于Xamarin的advanced使用者提供。

使用VisualStudioforMac時,會在執行時,使用針對您在飛行上產生的程式碼,在幕後自動完成對應。

當您使用InterfaceBuilder來設計使用者介面時,您只會設計應用程式的外觀,而且會建立一些預設連接。

如果您想要以程式設計方式提取資訊、在執行時間變更控制項的行為,或在執行時間修改控制項,則必須將某些控制項系結至您的managed程式碼。

這會透過幾個步驟來完成: 將輸出的宣告新增至檔案的擁有者。

連線您的控制項加入檔案的擁有者。

將UI和連接儲存在XIB/筆尖檔案中。

在執行時間載入筆尖檔。

存取輸出口變數。

(1)到(3)的步驟包含在Apple的檔中,以InterfaceBuilder建立介面。

使用的是您的應用程式時,您的應用程式將需要建立衍生自UIViewController的類別。

它會實作為: publicclassMyViewController:UIViewController{ publicMyViewController(stringnibName,NSBundlebundle):base(nibName,bundle) { //Youcanhaveasmanyargumentsasyouwant,butyouneedtocall //thebaseconstructorwiththeprovidednibNameandbundle. } } 然後,若要從筆尖檔案載入您的ViewController,請執行下列動作: varcontroller=newMyViewController("HelloWorld",NSBundle.MainBundle,this); 這會從筆尖載入使用者介面。

現在,若要存取輸出,必須通知執行時間我們想要進行存取。

若要這樣做,UIViewController子類別需要宣告屬性,並使用[連線]屬性來標注它們。

例如: [Connect] UITextFieldUserName{ get{ return(UITextField)GetNativeField("UserName"); } set{ SetNativeField("UserName",value); } } 屬性實作為實際提取和儲存實際原生型別的值。

使用VisualStudioforMac和InterfaceBuilder時,您不需要擔心這一點。

VisualStudioforMac會使用編譯為專案一部分的部分類別中的程式碼,自動鏡像所有宣告的輸出。

選取器 程式設計的核心概念Objective-C是選取器。

您通常會遇到需要您傳遞選取器的Api,或預期您的程式碼會回應選取器。

在c#中建立新的選取器很簡單–您只要建立類別的新實例ObjCRuntime.Selector,並在需要它的API中的任何位置使用結果。

例如: varselector_add=newSelector("add:plus:"); 針對c#方法回應選取器呼叫,它必須繼承自NSObject型別,而c#方法則必須使用[Export]屬性以選取器名稱裝飾。

例如: publicclassMyMath:NSObject{ [Export("add:plus:")] intAdd(intfirst,intsecond) { returnfirst+second; } } 選取器名稱必須完全相符,包括所有的中間和尾端冒號(":")(如果有的話)。

NSObject函式 在所有衍生自NSObject的Xamarin中,大部分類別都會公開物件功能專屬的函式,但它們也會公開不同的非立即察覺的函式。

這些函式的使用方式如下: publicFoo(IntPtrhandle) 當執行時間需要將您的類別對應到未受管理的類別時,就會使用這個函式來具現化您的類別。

當您載入XIB/筆尖檔案時,就會發生這種情況。

此時,Objective-C執行時間會在非受控環境中建立物件,並呼叫這個函式以初始化managed端。

一般而言,您只需要使用控制碼參數呼叫基底函式,然後在主體中執行任何必要的初始化。

publicFoo() 這是類別的預設的函式,而在Xamarin提供的類別中,這會初始化NSObject類別,而且兩端的所有類別都會將此方法連結至類別上的Objective-Cinit方法。

publicFoo(NSObjectFlagx) 這個函式是用來初始化實例,但防止程式碼在結尾呼叫Objective-C"init"方法。

當您在您的函式上使用[Export])或已經透過另一個平均值完成初始化時,您通常會使用(此方式。

publicFoo(NSCodercoder) 當物件是從NSCoding實例初始化時,就會提供此函數。

例外狀況 在c#例外狀況中,XamarinAPI設計不會引發Objective-C例外狀況。

此設計會強制不會在一開始就將垃圾郵件傳送給Objective-C世界,而且必須產生的任何例外狀況都會由系結本身產生,然後才會將不正確資料傳遞給Objective-C世界。

通知 在iOS和OSX中,開發人員都可以訂閱由基礎平臺廣播的通知。

這是藉由使用NSNotificationCenter.DefaultCenter.AddObserver方法來完成。

AddObserver方法採用兩個參數,一個是您想要訂閱的通知,另一個則是引發通知時要叫用的方法。

在Xamarin和Xamarin中,各種通知的金鑰都裝載在觸發通知的類別上。

例如,所引發UIMenuController的通知會以名稱為"Notification"的UIMenuController類別,以屬性的形式staticNSString裝載。

記憶體管理 Xamarin具有垃圾收集行程,可在不再使用資源時,為您釋放資源。

除了垃圾收集行程之外,衍生自NSObject的所有物件都會執行System.IDisposable介面。

NSObject和IDisposable IDisposable公開介面是協助開發人員釋放可能封裝大型記憶體區塊的物件(例如,UIImage可能看起來只是無害指標,但可能指向2mb的影像)和其他重要和有限的資源(例如影片解碼緩衝區)。

NSObject會實IDisposable介面,也會實作為.Net處置模式。

這可讓NSObject子類別的開發人員覆寫Dispose行為,並視需要發行自己的資源。

例如,請考慮使用會保留一堆影像的此view控制器: classMenuViewController:UIViewController{ UIImagebreakfast,lunch,dinner; [...] publicoverridevoidDispose(booldisposing) { if(disposing){ if(breakfast!=null)breakfast.Dispose();breakfast=null; if(lunch!=null)lunch.Dispose();lunch=null; if(dinner!=null)dinner.Dispose();dinner=null; } base.Dispose(disposing) } } 處置managed物件時,它不再有用。

您仍然可能會有物件的參考,但此物件適用于目前所有意圖和用途不正確物件。

某些.NETApi會在您嘗試存取已處置物件上的任何方法時擲回ObjectDisposedException來確保這一點,例如: varimage=UIImage.FromFile("demo.png"); image.Dispose(); image.XXX=false;//thisatthispointisaninvalidoperation 即使您仍然可以存取變數"image",它其實是不正確參考,而且不再指向保留影像的Objective-C物件。

但是,以c#處置物件並不表示物件一定會被終結。

您只需要釋放c#對物件的參考。

Cocoa環境可能已保留參考,以供自己使用。

例如,如果您將UIImageView的影像屬性設定為影像,然後再處置影像,則基礎UIImageView已取得自己的參考,而且會保留這個物件的參考,直到它完成使用為止。

呼叫Dispose的時機 當您需要Mono以清除您的物件時,請呼叫Dispose。

可能的使用案例是當Mono無法得知您的NSObject實際上持有重要資源(例如記憶體或資訊集區)的參考時。

在這些情況下,您應該呼叫Dispose來立即釋放記憶體的參考,而不是等候Mono執行垃圾收集迴圈。

在內部,當Mono從c#字串建立NSString的參考時,它會立即處置它們,以減少垃圾收集行程必須執行的工作量。

要處理的物件越少,GC的執行速度就愈快。

保留物件參考的時機 自動記憶體管理有一個副作用,就是GC將會去除未使用的物件,只要沒有它們的參考。

有時候可能會有驚訝的副作用,例如,如果您建立一個區域變數來保存最上層的視圖控制器或最上層的視窗,然後讓這些變數消失在後方。

如果您未將靜態或執行個體變數中的參考保留給物件,Mono會很高興地在其上呼叫Dispose()方法,而且會釋放物件的參考。

由於這可能是唯一未完成的參考,Objective-C執行時間會為您終結物件。

相關連結 系結欄位 本文內容



請為這篇文章評分?