逐步解說:系結 iOS Objective-C 連結庫
重要
我們目前正在調查 Xamarin 平臺上的自定義系結使用方式。 請接受 這項調查 ,以通知未來的開發工作。
本文提供針對現有 Objective-C 連結庫 InfColorPicker 建立 Xamarin.iOS 系結的實作逐步解說。 其涵蓋的主題包括編譯靜態 Objective-C 庫、系結靜態庫,以及在 Xamarin.iOS 應用程式中使用系結。
在 iOS 上工作時,您可能會遇到想要取用第三方 Objective-C 連結庫的情況。 在這些情況下,您可以使用 Xamarin.iOS 系結專案 來建立 C# 系結 ,讓您在 Xamarin.iOS 應用程式中取用連結庫。
一般而言,在iOS生態系統中,您可以找到3種類別的連結庫:
- 做為先行編譯的靜態庫檔案,擴展名
.a
與其標頭(s) (.h 檔案) 一起。 例如, Google 的分析連結庫 - 做為先行編譯架構。 這隻是包含靜態庫、標頭,有時使用
.framework
擴充功能的其他資源的資料夾。 例如, Google 的 AdMob Library。 - 就像原始碼檔案一樣。 例如,包含 Just
.m
和.h
Objective C 檔案的連結庫。
在第一個和第二個案例中,已經有先行編譯的CocoaTouch靜態庫,因此在本文中,我們將著重於第三個案例。 請記住,在您開始建立系結之前,請一律檢查連結庫所提供的授權,以確保您可以自由系結它。
本文提供使用 開放原始碼 InfColorPickerObjective-C 專案建立系結專案的逐步解說,不過本指南中的所有資訊都可以調整為搭配任何第三方Objective-C連結庫使用。 InfColorPicker 連結庫提供可重複使用的檢視控制器,可讓用戶根據其 HSB 表示法選取色彩,讓使用者更容易選擇色彩。
我們將涵蓋在 Xamarin.iOS 中取用此特定 Objective-C API 所需的所有必要步驟:
- 首先,我們將使用 Xcode 建立 Objective-C 靜態庫。
- 然後,我們會將此靜態庫與 Xamarin.iOS 系結。
- 接下來,示範 Objective Sharpie 如何藉由自動產生 Xamarin.iOS 系結所需的部分 API 定義來減少工作負載。
- 最後,我們將建立使用系結的 Xamarin.iOS 應用程式。
範例應用程式將示範如何使用強式委派,在 InfColorPicker API 和 C# 程式代碼之間進行通訊。 當我們瞭解如何使用強委派之後,我們將討論如何使用弱式委派來執行相同的工作。
需求
本文假設您已熟悉 Xcode 和語言, Objective-C 而且您已閱讀我們的 系結 Objective-C 檔。 此外,需要下列專案才能完成呈現的步驟:
- Xcode 和 iOS SDK - 必須在開發人員的電腦上安裝並設定 Apple 的 Xcode 和最新的 iOS API。
- Xcode 命令行工具 - Xcode 命令行工具 必須針對目前安裝的 Xcode 版本安裝(請參閱下方的安裝詳細數據)。
- Visual Studio for Mac 或 Visual Studio - 應在開發電腦上安裝及設定最新版本的 Visual Studio for Mac 或 Visual Studio。 開發 Xamarin.iOS 應用程式需要 Apple Mac,而且在使用 Visual Studio 時,您必須連線到 Xamarin.iOS 組建主機
- 最新版的 Objective Sharpie - 從這裡下載的 Objective Sharpie 工具目前的複本。 如果您已安裝 Objective Sharpie,您可以使用 將它更新為最新版本
sharpie update
安裝 Xcode 命令行工具
如上所述,我們將在本逐步解說中使用 Xcode 命令行工具(特別是 make
和 lipo
)。 make
此命令是一個非常常見的 Unix 公用程式,會使用 makefile 來自動編譯可執行的程式和連結庫,以指定程式應該如何建置。 此命令 lipo
是用來建立多架構檔案的OS X命令行公用程式;它會將所有硬體架構使用的多個 .a
檔案合併成一個檔案。
根據 Apple 使用 Xcode 的命令行建置常見問題檔,在 OS X 10.9 和更新版本中,[Xcode 喜好設定] 對話框的 [下載] 窗格不再支援下載命令行工具。
您必須使用下列其中一種方法來安裝工具:
安裝 Xcode - 當您安裝 Xcode 時,它隨附於所有命令行工具。 在OS X 10.9 填充碼中(安裝在 中
/usr/bin
),可以將隨附/usr/bin
的任何工具對應至 Xcode 內的對應工具。 例如,xcrun
命令可讓您從命令行尋找或執行 Xcode 內的任何工具。終端機應用程式 - 從終端機應用程式 ,您可以執行
xcode-select --install
命令來安裝命令行工具:- 啟動終端機應用程式。
- 輸入
xcode-select --install
並按 Enter,例如:
Europa:~ kmullins$ xcode-select --install
Apple 開發人員 的下載 - 命令行工具套件提供 Apple Developer 的 下載網頁。 使用您的 Apple ID 登入,然後搜尋並下載命令列工具:
安裝命令行工具之後,我們已準備好繼續進行逐步解說。
逐步解說
在本逐步解說中,我們將討論下列步驟:
- 建立靜態庫 - 此步驟牽涉到建立 InfColorPickerObjective-C 程式代碼的靜態連結庫。 靜態庫會有
.a
擴展名,而且會內嵌到連結庫專案的 .NET 元件中。 - 建立 Xamarin.iOS 系結專案 - 一旦有靜態庫,我們將用它來建立 Xamarin.iOS 系結專案。 系結專案是由我們剛才建立的靜態庫和 C# 程式代碼形式的元數據所組成,說明如何使用 Objective-C API。 此元數據通常稱為 API 定義。 我們將使用 Objective Sharpie 來協助我們建立 API 定義。
- 將 API 定義 正規化 - Objective Sharpie 會執行協助我們的絕佳工作,但無法執行所有作業。 我們將討論一些我們需要對 API 定義進行的變更,才能使用它們。
- 使用系結連結庫 - 最後,我們將建立 Xamarin.iOS 應用程式來示範如何使用新建立的系結專案。
既然我們瞭解涉及哪些步驟,讓我們繼續進行其餘的逐步解說。
建立靜態庫
如果我們檢查 Github 中 InfColorPicker 的程式代碼:
我們可以在專案中看到下列三個目錄:
- InfColorPicker - 此目錄包含 Objective-C 項目的程式代碼。
- PickerSamplePad - 此目錄包含範例 iPad 專案。
- PickerSample 電話 - 此目錄包含範例 i 電話 專案。
讓我們從 GitHub 下載 InfColorPicker 專案,並將其解壓縮到您選擇的目錄中。 開啟專案的 Xcode 目標 PickerSamplePhone
,我們會在 Xcode Navigator 中看到下列項目結構:
此專案可藉由將 InfColorPicker 原始碼(在紅色方塊中)直接新增至每個範例專案,以達到程式代碼重複使用。 範例專案的程式代碼位於藍色方塊內。 由於此特定專案未提供靜態庫,因此必須建立 Xcode 專案來編譯靜態庫。
第一個步驟是讓我們將 InfoColorPicker 原始程式碼新增至靜態庫。 若要達成此目的,讓我們執行下列動作:
啟動 Xcode。
從 [檔案] 功能表中,選取 [新增>專案...]:
選取 [架構與連結庫]、[Cocoa Touch Static Library] 範本,然後按兩下 [下一步] 按鈕:
針對 [項目名稱] 輸入
InfColorPicker
,然後按下一步[ 下一步] 按鈕:選取要儲存專案的位置,然後按下 [ 確定] 按鈕。
現在,我們需要將來源從 InfColorPicker 專案新增至靜態庫專案。 因為 InfColorPicker.h 檔案已存在於靜態庫中(根據預設),因此 Xcode 不允許我們覆寫它。 從 Finder,流覽至從 GitHub 解壓縮的原始專案中的 InfColorPicker 原始程式碼,複製所有 InfColorPicker 檔案,並將其貼到新的靜態庫專案中:
返回 Xcode,以滑鼠右鍵按兩下 InfColorPicker 資料夾,然後選取 [ 將檔案新增至 “InfColorPicker...”:
從 [新增檔案] 對話框,瀏覽至我們剛才複製的 InfColorPicker 原始碼檔案,選取它們全部,然後按兩下 [ 新增 ] 按鈕:
原始碼將會複製到我們的專案中:
從 Xcode 專案導覽器中,選取 InfColorPicker.m 檔案並批注出最後兩行(因為撰寫此連結庫的方式,因此不會使用此檔案):
我們現在需要檢查連結庫是否需要任何架構。 您可以在自述檔中找到這項資訊,或開啟提供的其中一個範例專案。 此範例會使用
Foundation.framework
、UIKit.framework
和CoreGraphics.framework
,讓我們新增它們。選取 InfColorPicker 目標 > 建置階段 ,然後展開 [ 連結二進位與連結庫 ] 區段:
+使用 按鈕開啟對話框,讓您新增上面所列的必要框架架構:
[ 鏈接二進位與連結庫 ] 區段現在看起來應該像下圖:
此時我們很接近,但我們並沒有完全完成。 靜態庫已建立,但我們需要建置它,以建立 Fat 二進位檔,其中包含 iOS 裝置和 iOS 模擬器所需的所有架構。
建立 Fat 二進位檔
所有 iOS 裝置都有由經過一段時間開發的 ARM 架構所支援的處理器。 每個新架構都新增了新的指示和其他改善,同時仍維持回溯相容性。 iOS 裝置具有armv6、armv7、armv7s、arm64 指令集 –雖然armv6 不再使用。 iOS 模擬器不是由 ARM 提供電源,而是 x86 和 x86_64電源模擬器。 這表示必須為每個指令集提供連結庫。
Fat 連結庫是 .a
包含所有支援架構的檔案。
建立胖二進位檔是三個步驟的程式:
- 編譯靜態庫的 ARM 7 和 ARM64 版本。
- 編譯 x86 和x84_64版本的靜態庫。
lipo
使用命令行工具,將兩個靜態庫合併成一個。
雖然這三個步驟相當簡單,但在連結庫收到更新或我們需要錯誤修正時 Objective-C ,可能需要在未來重複這些步驟。 如果您決定將這些步驟自動化,它會簡化 iOS 系結專案的未來維護和支援。
有許多工具可用來自動化這類工作 - 殼層腳本、 rake、 xbuild 和 make。 安裝 Xcode 命令行工具時, make
也會安裝 ,因此這是將用於本逐步解說的建置系統。 以下是一個 Makefile ,可用來建立可在 iOS 裝置上運作的多架構共用連結庫,以及任何連結庫的模擬器:
XBUILD=/Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild
PROJECT_ROOT=./YOUR-PROJECT-NAME
PROJECT=$(PROJECT_ROOT)/YOUR-PROJECT-NAME.xcodeproj
TARGET=YOUR-PROJECT-NAME
all: lib$(TARGET).a
lib$(TARGET)-i386.a:
$(XBUILD) -project $(PROJECT) -target $(TARGET) -sdk iphonesimulator -configuration Release clean build
-mv $(PROJECT_ROOT)/build/Release-iphonesimulator/lib$(TARGET).a $@
lib$(TARGET)-armv7.a:
$(XBUILD) -project $(PROJECT) -target $(TARGET) -sdk iphoneos -arch armv7 -configuration Release clean build
-mv $(PROJECT_ROOT)/build/Release-iphoneos/lib$(TARGET).a $@
lib$(TARGET)-arm64.a:
$(XBUILD) -project $(PROJECT) -target $(TARGET) -sdk iphoneos -arch arm64 -configuration Release clean build
-mv $(PROJECT_ROOT)/build/Release-iphoneos/lib$(TARGET).a $@
lib$(TARGET).a: lib$(TARGET)-i386.a lib$(TARGET)-armv7.a lib$(TARGET)-arm64.a
xcrun -sdk iphoneos lipo -create -output $@ $^
clean:
-rm -f *.a *.dll
在您選擇的純文本編輯器中輸入 Makefile 命令,並以 YOUR-PROJECT-NAME 更新區段,並以專案名稱更新這些區段。 請務必確保完全貼上上述指示,並保留指示內的索引標籤。
將名稱 Makefile 的檔案儲存到與上述所建立 InfColorPicker Xcode 靜態庫相同的位置:
開啟 Mac 上的終端機應用程式,並流覽至 Makefile 的位置。 輸入 make
終端機,按 Enter 鍵, 然後執行 Makefile :
當您執行 Make 時,您會看到許多文字捲動。 如果一切正常運作,您會看到 BUILD SUCCEEDED 和 libInfColorPicker-armv7.a
檔案libInfColorPickerSDK.a
libInfColorPicker-i386.a
會複製到與 Makefile 相同的位置:
您可以使用下列命令來確認 Fat 二進位檔內的架構:
xcrun -sdk iphoneos lipo -info libInfColorPicker.a
這應該會顯示下列內容:
Architectures in the fat file: libInfColorPicker.a are: i386 armv7 x86_64 arm64
此時,我們已完成 iOS 系結的第一個步驟,方法是使用 Xcode 和 Xcode 命令行工具和 make
lipo
建立靜態庫。 讓我們移至下一個步驟,並使用 Objective-Sharpie 來自動為我們建立 API 系結。
建立 Xamarin.iOS 系結專案
在我們可以使用 Objective-Sharpie 將系結程式自動化之前,我們需要建立 Xamarin.iOS 系結專案來存放 API 定義(我們將使用 Objective-Sharpie 來協助我們建置),併為我們建立 C# 系結。
讓我們執行下列動作:
啟動 Visual Studio for Mac。
從 [檔案] 選單中,選取 [新增>解決方案...]:
從 [新增方案] 對話框中,選取 [鏈接庫>iOS 系結專案]:
按一下 [下一步] 按鈕。
輸入 “InfColorPickerBinding” 作為 [專案名稱 ],然後按兩下 [ 建立 ] 按鈕以建立方案:
將會建立解決方案,並包含兩個預設檔案:
- ApiDefinition.cs - 此檔案將包含定義 Objective-C API 如何包裝在 C# 中的合約。
- Structs.cs - 此檔案會保存介面和委派所需的任何結構或列舉值。
我們將在稍後的逐步解說中使用這兩個檔案。 首先,我們需要將 InfColorPicker 連結庫新增至系結專案。
在系結專案中加入靜態庫
現在我們已經備妥基底系結項目,我們需要新增我們針對 InfColorPicker 連結庫所建立的 Fat Binary 連結庫。
請遵循下列步驟來新增連結庫:
以滑鼠右鍵按兩下 Solution Pad 中的 [原生參考 ] 資料夾,然後選取 [ 新增原生參考]:
瀏覽至我們稍早製作的 [胖二進位檔],
libInfColorPickerSDK.a
然後按 [ 開啟 ] 按鈕:檔案將會包含在專案中:
將 .a 檔案新增至專案時,Xamarin.iOS 會自動將檔案的建置動作設定為 ObjcBindingNativeLibrary,並建立名為 libInfColorPickerSDK.linkwith.cs
的特殊檔案。
此檔案包含 LinkWith
屬性,告知 Xamarin.iOS 如何處理我們剛才新增的靜態庫。 此檔案的內容會顯示在下列代碼段:
using ObjCRuntime;
[assembly: LinkWith ("libInfColorPickerSDK.a", SmartLink = true, ForceLoad = true)]
屬性 LinkWith
會識別專案的靜態連結庫和一些重要的連結器旗標。
我們需要做的下一件事是建立 InfColorPicker 專案的 API 定義。 為了本逐步解說的目的,我們將使用 Objective Sharpie 來產生檔案 ApiDefinition.cs。
使用 Objective Sharpie
Objective Sharpie 是命令行工具(由 Xamarin 提供),可協助建立將第三方 Objective-C 連結庫系結至 C# 所需的定義。 在本節中,我們將使用 Objective Sharpie 建立 InfColorPicker 專案的初始 ApiDefinition.cs 。
若要開始使用,讓我們下載 Objective Sharpie 安裝程式檔案,如本指南所述。 執行安裝程式,並遵循安裝精靈中的所有螢幕上提示,在我們的開發計算機上安裝 Objective Sharpie。
成功安裝 Objective Sharpie 之後,讓我們啟動終端機應用程式,並輸入下列命令以取得其提供以協助系結之所有工具的說明:
sharpie -help
如果我們執行上述命令,將會產生下列輸出:
Europa:Resources kmullins$ sharpie -help
usage: sharpie [OPTIONS] TOOL [TOOL_OPTIONS]
Options:
-h, --helpShow detailed help
-v, --versionShow version information
Available Tools:
xcode Get information about Xcode installations and available SDKs.
pod Create a Xamarin C# binding to Objective-C CocoaPods
bind Create a Xamarin C# binding to Objective-C APIs
update Update to the latest release of Objective Sharpie
verify-docs Show cross reference documentation for [Verify] attributes
docs Open the Objective Sharpie online documentation
為了進行本逐步解說,我們將使用下列 Objective Sharpie 工具:
- xcode - 此工具提供我們目前 Xcode 安裝的相關信息,以及我們已安裝的 iOS 和 Mac API 版本。 我們稍後會在產生系結時使用這項資訊。
- bind - 我們將使用此工具,將 InfColorPicker 專案中的 .h 檔案剖析為初始ApiDefinition.cs和StructsAndEnums.cs檔案。
若要取得特定 Objective Sharpie 工具的說明,請輸入工具的名稱和 -help
選項。 例如, sharpie xcode -help
傳回下列輸出:
Europa:Resources kmullins$ sharpie xcode -help
usage: sharpie xcode [OPTIONS]+
Options:
-h, -help Show detailed help
-v, -verbose Be verbose with output
Xcode Options:
-sdks List all available Xcode SDKs. Pass -verbose for more
details.
-sdkpath SDK Output the path of the SDK
-frameworks SDK List all available framework directories in a given SDK.
在開始系結程式之前,我們需要在終端 sharpie xcode -sdks
機中輸入下列命令,以取得目前已安裝 SDK 的相關信息:
amyb:Desktop amyb$ sharpie xcode -sdks
sdk: appletvos9.2 arch: arm64
sdk: iphoneos9.3 arch: arm64 armv7
sdk: macosx10.11 arch: x86_64 i386
sdk: watchos2.2 arch: armv7
從上述內容中,我們可以看到計算機上已安裝 iphoneos9.3
SDK。 有了這項資訊,我們就可以將 InfColorPicker 專案 .h
檔剖析成初始 ApiDefinition.cs 以及 StructsAndEnums.cs
InfColorPicker 專案。
在終端機應用程式中輸入下列命令:
sharpie bind --output=InfColorPicker --namespace=InfColorPicker --sdk=[iphone-os] -scope [full-path-to-project]/InfColorPicker/InfColorPicker [full-path-to-project]/InfColorPicker/InfColorPicker/*.h
其中 [full-path-to-project]
是 InfColorPicker Xcode 專案檔位於電腦所在目錄的完整路徑,而 [iphone-os] 是我們安裝的 iOS SDK,如 命令所sharpie xcode -sdks
指出。 請注意,在此範例中,我們傳遞 了 *.h 作為參數,其中包含 此目錄中的所有 頭檔 - 通常您不應該這麼做,而是仔細閱讀頭檔,以尋找參考所有其他相關檔案的最上層 .h 檔案,並直接傳遞至 Objective Sharpie。
提示
針對 自 -scope
變數,傳入具有您要系結之標頭的資料夾。
如果沒有 自 -scope
變數,Objective Sharpie 會嘗試為匯入的任何 iOS SDK 標頭產生系結,例如 #import <UIKit.h>
,導致編譯系結專案時可能會產生錯誤的龐大定義檔案。 設定自變數之後 -scope
,Objective Sharpie 將不會為範圍資料夾以外的任何標頭產生系結。
終端機中會產生下列 輸出 :
Europa:Resources kmullins$ sharpie bind -output InfColorPicker -namespace InfColorPicker -sdk iphoneos8.1 /Users/kmullins/Projects/InfColorPicker/InfColorPicker/InfColorPicker.h -unified
Compiler configuration:
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk -miphoneos-version-min=8.1 -resource-dir /Library/Frameworks/ObjectiveSharpie.framework/Versions/1.1.1/clang-resources -arch armv7 -ObjC
[ 0%] parsing /Users/kmullins/Projects/InfColorPicker/InfColorPicker/InfColorPicker.h
In file included from /Users/kmullins/Projects/InfColorPicker/InfColorPicker/InfColorPicker.h:60:
/Users/kmullins/Projects/InfColorPicker/InfColorPicker/InfColorPickerController.h:28:1: warning: no 'assign',
'retain', or 'copy' attribute is specified - 'assign' is assumed [-Wobjc-property-no-attribute]
@property (nonatomic) UIColor* sourceColor;
^
/Users/kmullins/Projects/InfColorPicker/InfColorPicker/InfColorPickerController.h:28:1: warning: default property
attribute 'assign' not appropriate for non-GC object [-Wobjc-property-no-attribute]
/Users/kmullins/Projects/InfColorPicker/InfColorPicker/InfColorPickerController.h:29:1: warning: no 'assign',
'retain', or 'copy' attribute is specified - 'assign' is assumed [-Wobjc-property-no-attribute]
@property (nonatomic) UIColor* resultColor;
^
/Users/kmullins/Projects/InfColorPicker/InfColorPicker/InfColorPickerController.h:29:1: warning: default property
attribute 'assign' not appropriate for non-GC object [-Wobjc-property-no-attribute]
4 warnings generated.
[100%] parsing complete
[bind] InfColorPicker.cs
Europa:Resources kmullins$
InfColorPicker.enums.cs和InfColorPicker.cs檔案將會在我們的目錄中建立:
在上述建立的 Binding 項目中開啟這兩個檔案。 複製InfColorPicker.cs檔案的內容,並將其貼到ApiDefinition.cs檔案中,將現有的namespace ...
程式代碼區塊取代為InfColorPicker.cs檔案的內容(讓using
語句保持不變):
標準化 API 定義
Objective Sharpie 有時有轉譯 Delegates
的問題,因此我們必須修改 介面的定義 InfColorPickerControllerDelegate
,並以下列程式代碼取代 [Protocol, Model]
行:
[BaseType(typeof(NSObject))]
[Model]
如此一來,定義看起來會像這樣:
接下來,我們會對檔案的內容 InfColorPicker.enums.cs
執行相同的動作,複製並貼到檔案中 StructsAndEnums.cs
,讓 using
語句保持不變:
您也可以發現 Objective Sharpie 已使用 [Verify]
屬性標註系結。 這些屬性表示您應該藉由比較系結與原始 C/Objective-C 宣告來驗證 Objective Sharpie 執行正確的動作(將在系結宣告上方的批注中提供)。 驗證系結之後,您應該移除 verify 屬性。 如需詳細資訊,請參閱 驗證 指南。
此時,我們的系結項目應該已完成並準備好建置。 讓我們建置我們的系結專案,並確定我們最終不會發生任何錯誤:
使用系結
請遵循下列步驟來建立範例 i 電話 應用程式,以使用上面建立的 iOS 系結連結庫:
建立 Xamarin.iOS 專案 - 將名為 InfColorPickerSample 的新 Xamarin.iOS 專案新增至解決方案,如下列螢幕快照所示:
新增系結項目的參考 - 更新 InfColorPickerSample 專案,使其具有 InfColorPickerBinding 項目的參考:
建立 i 電話 使用者介面 - 按兩下 InfColorPickerSample 專案中的 MainStoryboard.storyboard 檔案,以在 iOS 設計工具中編輯它。 將 Button 新增至檢視並呼叫它
ChangeColorButton
,如下所示:新增 InfColorPickerView.xib - InfColorPicker Objective-C 連結庫包含 .xib 檔案。 Xamarin.iOS 不會在系結專案中包含這個 .xib ,這會導致範例應用程式中的運行時間錯誤。 其因應措施是將 .xib 檔案新增至 Xamarin.iOS 專案。 選取 Xamarin.iOS 專案,以滑鼠右鍵按下並選取 [新增>檔案],然後新增 .xib 檔案,如下列螢幕快照所示:
當系統詢問時,請將 .xib 檔案複製到專案中。
接下來,讓我們快速查看 中的 Objective-C 通訊協定,以及如何在系結和 C# 程式代碼中處理它們。
通訊協定和 Xamarin.iOS
在 中 Objective-C,通訊協定會定義可用於特定情況的方法(或訊息)。 就概念上講,它們與 C# 中的介面非常類似。 通訊協定與 C# 介面之間的 Objective-C 其中一個主要差異是通訊協定可以有選擇性方法 - 類別不需要實作的方法。 Objective-C@optional會使用 關鍵詞來指出哪些方法是選擇性的。 如需通訊協議的詳細資訊,請參閱 事件、通訊協定和委派。
InfColorPickerController 有一個這類通訊協定,如下列代碼段所示:
@protocol InfColorPickerControllerDelegate
@optional
- (void) colorPickerControllerDidFinish: (InfColorPickerController*) controller;
// This is only called when the color picker is presented modally.
- (void) colorPickerControllerDidChangeColor: (InfColorPickerController*) controller;
@end
InfColorPickerController 會使用此通訊協定來通知用戶端使用者已挑選新的色彩,且 InfColorPickerController 已完成。 Objective Sharpie 對應此通訊協定,如下列代碼段所示:
[BaseType(typeof(NSObject))]
[Model]
public partial interface InfColorPickerControllerDelegate {
[Export ("colorPickerControllerDidFinish:")]
void ColorPickerControllerDidFinish (InfColorPickerController controller);
[Export ("colorPickerControllerDidChangeColor:")]
void ColorPickerControllerDidChangeColor (InfColorPickerController controller);
}
編譯系結連結庫時,Xamarin.iOS 會建立稱為 InfColorPickerControllerDelegate
的抽象基類,以虛擬方法實作這個介面。
有兩種方式可以在 Xamarin.iOS 應用程式中實作這個介面:
- 強委派 - 使用強委派 牽涉到建立 C# 類別,以子類別
InfColorPickerControllerDelegate
和覆寫適當的方法。 InfColorPickerController 會使用此類別的實例與其客戶端通訊。 - 弱式委派 - 弱式委派是一種稍微不同的技術,涉及在某些類別上建立公用方法(例如
InfColorPickerSampleViewController
),然後透過Export
屬性將該方法公開至InfColorPickerDelegate
通訊協定。
強委派提供 Intellisense、類型安全性,以及更佳的封裝。 基於這些原因,您應該使用強委派,而不是弱式委派。
在本逐步解說中,我們將討論這兩種技術:先實作強委派,然後說明如何實作弱式委派。
實作強委派
使用強委派來回應 colorPickerControllerDidFinish:
訊息,以完成 Xamarin.iOS 應用程式:
子類別 InfColorPickerControllerDelegate - 將新類別新增至名為 ColorSelectedDelegate
的專案。 編輯類別,使其具有下列程式代碼:
using InfColorPickerBinding;
using UIKit;
namespace InfColorPickerSample
{
public class ColorSelectedDelegate:InfColorPickerControllerDelegate
{
readonly UIViewController parent;
public ColorSelectedDelegate (UIViewController parent)
{
this.parent = parent;
}
public override void ColorPickerControllerDidFinish (InfColorPickerController controller)
{
parent.View.BackgroundColor = controller.ResultColor;
parent.DismissViewController (false, null);
}
}
}
Xamarin.iOS 會藉由建立稱為 InfColorPickerControllerDelegate
的抽象基類來Objective-C系結委派。 這個型別的 ColorPickerControllerDidFinish
子類別,並覆寫 方法來存取 ResultColor
的屬性值 InfColorPickerController
。
建立 ColorSelectedDelegate 的實例 - 我們的事件處理程式將需要我們在上一個步驟中建立的類型 ColorSelectedDelegate
實例。 編輯 類別 InfColorPickerSampleViewController
,並將下列實例變數新增至 類別:
ColorSelectedDelegate selector;
初始化 ColorSelectedDelegate 變數 - 若要確保selector
為有效的實例,請更新 中的 ViewController
方法ViewDidLoad
以符合下列代碼段:
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
ChangeColorButton.TouchUpInside += HandleTouchUpInsideWithStrongDelegate;
selector = new ColorSelectedDelegate (this);
}
實作 HandleTouchUpInsideWithStrongDelegate 方法 - 下一步會在使用者觸碰 ColorChangeButton 時實作 的事件處理程式。 編輯 ViewController
,並新增下列方法:
using InfColorPicker;
...
private void HandleTouchUpInsideWithStrongDelegate (object sender, EventArgs e)
{
InfColorPickerController picker = InfColorPickerController.ColorPickerViewController();
picker.Delegate = selector;
picker.PresentModallyOverViewController (this);
}
我們先透過靜態方法取得的 InfColorPickerController
實例,並透過 屬性 InfColorPickerController.Delegate
知道強委派。 Objective Sharpie 會自動為我們產生這個屬性。 最後,我們呼叫 PresentModallyOverViewController
來顯示檢視 InfColorPickerSampleViewController.xib
,讓使用者可以選取色彩。
執行應用程式 - 此時,我們已完成所有程序代碼。 如果您執行應用程式,您應該能夠變更 的背景色彩 InfColorColorPickerSampleView
,如下列螢幕快照所示:
恭喜! 此時,您已成功建立並系結 Objective-C 連結庫以用於 Xamarin.iOS 應用程式。 接下來,讓我們來瞭解如何使用弱式委派。
實作弱式委派
Xamarin.iOS 除了將系結至特定委派之通訊協定的 Objective-C 類別進行子類別化,也可讓您在任何衍生自 NSObject
的類別中實作通訊協定方法,以 裝飾您的方法 ExportAttribute
,然後提供適當的選取器。 當您採用此方法時,您會將 類別的實例指派給 屬性, WeakDelegate
而不是 指派給 Delegate
屬性。 弱式委派可讓您彈性地將委派類別帶下不同的繼承階層。 讓我們看看如何在 Xamarin.iOS 應用程式中實作和使用弱式委派。
建立 TouchUpInside 的事件處理程式 - 讓我們為 TouchUpInside
[變更背景色彩] 按鈕的事件建立新的事件處理程式。 此處理程式會填入與我們在上一節中建立的 HandleTouchUpInsideWithStrongDelegate
處理程式相同的角色,但會使用弱式委派,而不是強委派。 編輯 類別 ViewController
,並新增下列方法:
private void HandleTouchUpInsideWithWeakDelegate (object sender, EventArgs e)
{
InfColorPickerController picker = InfColorPickerController.ColorPickerViewController();
picker.WeakDelegate = this;
picker.SourceColor = this.View.BackgroundColor;
picker.PresentModallyOverViewController (this);
}
更新 ViewDidLoad - 我們必須變更 ViewDidLoad
,讓它使用剛才建立的事件處理程式。 編輯 ViewController
並變更 ViewDidLoad
為類似下列代碼段:
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
ChangeColorButton.TouchUpInside += HandleTouchUpInsideWithWeakDelegate;
}
處理 colorPickerControllerDidFinish:Message - 完成時 ViewController
,iOS 會將訊息 colorPickerControllerDidFinish:
傳送至 WeakDelegate
。 我們需要建立可處理此訊息的 C# 方法。 若要這樣做,我們會建立 C# 方法,然後使用 加以 ExportAttribute
裝飾。 編輯 ViewController
,並將下列方法新增至 類別:
[Export("colorPickerControllerDidFinish:")]
public void ColorPickerControllerDidFinish (InfColorPickerController controller)
{
View.BackgroundColor = controller.ResultColor;
DismissViewController (false, null);
}
執行應用程式。 它現在的行為應該與之前完全相同,但它使用弱式委派,而不是強委派。 此時,您已成功完成本逐步解說。 您現在應該已瞭解如何建立及取用 Xamarin.iOS 系結專案。
摘要
本文逐步解說了建立和使用 Xamarin.iOS 系結項目的程式。 首先,我們已討論如何將現有的 Objective-C 連結庫編譯成靜態庫。 然後,我們討論如何建立 Xamarin.iOS 系結專案,以及如何使用 Objective Sharpie 來產生連結庫的 Objective-C API 定義。 我們已討論如何更新和調整產生的 API 定義,使其適合用於公用取用。 完成 Xamarin.iOS 系結專案之後,我們繼續在 Xamarin.iOS 應用程式中取用該系結,重點是使用強委派和弱式委派。