チュートリアル - iOS Objective-C ライブラリのバインド
重要
現在、Xamarin プラットフォームでのカスタム バインディングの使用を調査しています。 今後の開発作業の発展のために、このアンケートにご回答ください。
この記事では、既存の Objective-C ライブラリである InfColorPicker 用に Xamarin.iOS バインドを作成する実践的なチュートリアルを提供します。 スタティック Objective-C ライブラリのコンパイル、バインド、Xamarin.iOS アプリケーションでのバインドの使用などのトピックを扱います。
iOS 上で作業しているときに、サードパーティの Objective-C ライブラリを使いたい状況になることがあります。 このような状況では、Xamarin.iOS バインド プロジェクトを使用して、Xamarin.iOS アプリケーションでライブラリを使用できるようにする C# バインドを作成できます。
一般に、iOS エコシステムには、次の 3 種類のライブラリがあります。
.a
拡張機能とそのヘッダー (.h ファイル) を持つプリコンパイル済みスタティック ライブラリ ファイルとして。 たとえば、Google アナリティクス ライブラリ- プリコンパイル済みフレームワークとして。 これは、スタティック ライブラリ、ヘッダー、場合によっては
.framework
拡張機能などの追加のリソースが格納された単なるフォルダーである場合があります。 例として、Google の AdMob ライブラリがあります。 - 単なるソース コード ファイルとして。 たとえば、
.m
ファイルと.h
Objective-C ファイルを含むライブラリなどです。
1 番目と 2 番目のシナリオでは、プリコンパイル済みの CocoaTouch スタティック ライブラリが既に存在するため、この記事では 3 番目のシナリオに焦点を当てます。 バインドの作成を開始する前に、ライブラリに付属のライセンスを必ず確認し、ライブラリを自由にバインドできることを確認してください。
この記事では、オープンソースの 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 ユーティリティです。 lipo
コマンドは、複数のアーキテクチャ ファイルを作成するための OS X コマンド ライン ユーティリティです。複数の .a
ファイルを 1 つのファイルに結合し、これをすべてのハードウェア アーキテクチャで使用できます。
Apple の Xcode を使用したコマンド ラインからのビルド FAQ ドキュメントによると、OS X 10.9 以降では、Xcode の [Preferences] ダイアログの [Downloads] ウィンドウでは、コマンドライン ツールのダウンロードがサポートされなくなりました。
ツールをインストールするには、次のいずれかの方法を使用する必要があります。
Xcode のインストール - Xcode をインストールすると、すべてのコマンド ライン ツールにバンドルされます。 OS X 10.9 shim (
/usr/bin
にインストールされる) では、/usr/bin
に含まれる任意のツールを Xcode 内の対応するツールにマップできます。 たとえば、コマンド ラインから Xcode 内の任意のツールを検索または実行できるxcrun
コマンドです。ターミナル アプリケーション - ターミナル アプリケーションから、
xcode-select --install
コマンドを実行してコマンド ライン ツールをインストールできます。- ターミナル アプリケーションを起動します。
- 「
xcode-select --install
」と入力し、Enter キーを押します。次に例を示します。
Europa:~ kmullins$ xcode-select --install
Apple 開発者向けのダウンロード - コマンド ライン ツール パッケージは、Apple 開発者向けのダウンロード Web ページで入手できます。 Apple ID でログインし、次のようにコマンド ライン ツールを検索してダウンロードします。
コマンド ライン ツールがインストールされたので、チュートリアルを続行する準備ができました。
チュートリアル
このチュートリアルでは、次の手順について説明します。
- スタティック ライブラリの作成 - この手順では、InfColorPickerObjective-C コードのスタティック ライブラリを作成します。 スタティック ライブラリはファイル拡張子
.a
を持ち、ライブラリ プロジェクトの .NET アセンブリに埋め込まれます。 - Xamarin.iOS バインド プロジェクトの作成 - スタティック ライブラリを作成したら、それを使用して Xamarin.iOS バインド プロジェクトを作成します。 バインド プロジェクトは、先ほど作成したスタティック ライブラリと、Objective-C API を使用する方法を説明する C# コードの形式のメタデータで構成されます。 このメタデータは、一般に API 定義と呼ばれます。 Objective Sharpie を使用して、API 定義の作成に役立てます。
- API 定義の正規化 - Objective Sharpie には役立つ優れた機能がありますが、何でもしてくれるわけではありません。 API 定義を使用する前に行う必要があるいくつかの変更について説明します。
- バインド ライブラリの使用 - 最後に、Xamarin.iOS アプリケーションを作成して、新しく作成したバインド プロジェクトの使用方法を示します。
関連する手順を理解したので、チュートリアルの残りの部分に進みましょう。
スタティック ライブラリの作成
Github で InfColorPicker のコードを調べる場合:
プロジェクトには、次の 3 つのディレクトリが表示されます。
- InfColorPicker - このディレクトリには、プロジェクト用の Objective-C コードが格納されています。
- PickerSamplePad - このディレクトリには、サンプルの iPad プロジェクトが格納されています。
- PickerSamplePhone - このディレクトリには、サンプルの iPhone プロジェクトが格納されています。
GitHub から InfColorPicker プロジェクトをダウンロードし、選択したディレクトリに解凍してみましょう。 PickerSamplePhone
プロジェクトの Xcode ターゲットを開くと、Xcode ナビゲーターに次のプロジェクト構造が表示されます。
このプロジェクトでは、InfColorPicker ソース コード (赤いボックス内) を各サンプル プロジェクトに直接追加することで、コードの再利用を実現します。 サンプル プロジェクトのコードは青いボックス内にあります。 この特定のプロジェクトではスタティック ライブラリが提供されないため、スタティック ライブラリをコンパイルする Xcode プロジェクトを作成する必要があります。
その最初の手順では、InfoColorPicker ソース コードをスタティック ライブラリに追加します。 これを実現するには、次の操作を行います。
Xcode を起動します。
[File] メニューで [New]>[Project] を選択します。
[Framework & Library]、[Cocoa Touch Static Library] テンプレートを選択し、[Next] ボタンを選択します。
[Project Name] に「
InfColorPicker
」と入力し、[Next] ボタンをクリックします。プロジェクトを保存する場所を選択し、[OK] ボタンを選択します。
次に、InfColorPicker プロジェクトのソースをスタティック ライブラリ プロジェクトに追加する必要があります。 InfColorPicker.h ファイルはスタティック ライブラリに既に存在するため (既定)、Xcode では上書きできません。 [Finder] から、GitHub から解凍した元のプロジェクトの InfColorPicker ソース コードに移動し、すべての InfColorPicker ファイルをコピーして、新しいスタティック ライブラリ プロジェクトに貼り付けます。
Xcode に戻り、InfColorPicker フォルダーを右クリックし、[Add files to "InfColorPicker..."] を選択します。
[Add Files] ダイアログ ボックスで、先ほどコピーした InfColorPicker ソース コード ファイルに移動し、すべてを選択して、[Add] ボタンをクリックします。
ソース コードがプロジェクトにコピーされます。
Xcode プロジェクト ナビゲーターから InfColorPicker.m ファイルを選択し、最後の 2 行をコメント アウトします (このライブラリの記述方法のため、このファイルは使用されません)。
ライブラリに必要なフレームワークがあるかどうかを確認する必要があります。 この情報は、README で、または提供されているサンプル プロジェクトのいずれかを開いて確認できます。 この例では、
Foundation.framework
、UIKit.framework
、CoreGraphics.framework
を使用するので、それらを追加しましょう。[InfColorPicker target] > [Build Phases] を選択し、[Link Binary With Libraries] セクションを展開します。
+ ボタンを使用してダイアログを開き、上記の必要なフレームのフレームワークを追加できます。
[Link Binary With Libraries] セクションは、次の図のようになります。
この時点で完了に近付いていますが、まだ終わってはいません。 スタティック ライブラリは作成されましたが、これをビルドして、iOS デバイスと iOS シミュレーターの両方に必要なすべてのアーキテクチャを含むファット バイナリを作成する必要があります。
ファット バイナリの作成
すべての iOS デバイスには、経時的に開発された ARM アーキテクチャを搭載したプロセッサがあります。 各新しいアーキテクチャでは、下位互換性を維持しつつ、新しい命令やその他の機能強化が追加されています。 iOS デバイスには armv6、armv7、armv7s、arm64 の各命令セットがあります。ただし armv6 は現在では使用されていません。 iOS シミュレーターは ARM を搭載しておらず、代わりに x86 と x86_64 を搭載したシミュレーターです。 つまり、命令セットのそれぞれに対してライブラリを提供する必要があります。
ファット ライブラリは、サポートされているすべてのアーキテクチャを含む .a
ファイルです。
ファット バイナリを作成するには、次の 3 つの手順を実行します。
- ARM 7 と ARM64 バージョンのスタティック ライブラリをコンパイルします。
- x86 と x84_64 バージョンのスタティック ライブラリをコンパイルします。
lipo
コマンド ライン ツールを使用して、2 つのスタティック ライブラリを 1 つに結合します。
これらの 3 つの手順は単純ですが、Objective-C ライブラリが更新プログラムを受け取ったとき、またはバグ修正が必要な場合は、今後も同じ手順を実行する必要があります。 これらの手順を自動化すると、iOS バインド プロジェクトの将来のメンテナンスとサポートが簡略化されます。
このようなタスクを自動化するために使用できるツールは多数あります。シェル スクリプト、rake、xbuild、make です。 Xcode コマンド ライン ツールをインストールすると、make
もインストールされ、これがこのチュートリアルで使用されるビルド システムになります。 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
選択したプレーン テキスト エディターでメイクファイル コマンドを入力し、作成するプロジェクトの名前を使用して YOUR-PROJECT-NAME セクションを更新します。 また、上記の指示を正確に貼り付け、指示内のタブを保持することも重要です。
Makefile という名前で、上記で作成した InfColorPicker Xcode スタティック ライブラリと同じ場所にファイルを保存します。
Mac でターミナル アプリケーションを開き、メイクファイルの場所に移動します。 ターミナルに「make
」と入力し、Enter キーを押すと、メイクファイルが実行されます。
make を実行すると、テキストのスクロールが多数表示されます。 すべてが正常に機能した場合は、BUILD SUCCEEDED という文が表示され、libInfColorPicker-armv7.a
ファイル、libInfColorPicker-i386.a
ファイル、libInfColorPickerSDK.a
ファイルがメイクファイルと同じ場所にコピーされます。
次のコマンドを使用して、ファット バイナリ内のアーキテクチャを確認できます。
xcrun -sdk iphoneos lipo -info libInfColorPicker.a
これにより、次の内容が表示されます。
Architectures in the fat file: libInfColorPicker.a are: i386 armv7 x86_64 arm64
この時点で、Xcode と Xcode コマンド ライン ツール make
と lipo
を使用してスタティック ライブラリを作成し、iOS バインドの最初の手順を完了しました。 次の手順に進み、Objective-Sharpie を使用して、API バインドの作成を自動化しましょう。
Xamarin.iOS バインド プロジェクトの作成
Objective-Sharpie を使用してバインド プロセスを自動化するには、API 定義 (Objective-Sharpie を使用してビルドに役立てる) を格納する Xamarin.iOS バインド プロジェクトを作成し、C# バインディングを作成する必要があります。
次の操作を行います。
Visual Studio for Mac を起動します。
[File] メニューで、[New]>[Solution] を選択します。
[New Solution] ダイアログ ボックスで、[Library]>[iOS Binding Project] を選択します。
[次へ] をクリックします。
[Project Name] に「InfColorPickerBinding」と入力し、[Create] ボタンをクリックしてソリューションを作成します。
ソリューションが作成され、2 つの既定のファイルが含まれます。
- ApiDefinition.cs - このファイルに、Objective-C API を C# でラップする方法を定義するコントラクトが含まれます。
- Structs.cs - このファイルに、インターフェイスとデリゲートに必要なすべての構造体または列挙値が保持されます。
このチュートリアルの後半で、これら 2 つのファイルを操作します。 まず、InfColorPicker ライブラリをバインド プロジェクトに追加する必要があります。
バインド プロジェクトにスタティック ライブラリを含める
これで基本バインド プロジェクトの準備ができたので、上記で作成したファット バイナリ ライブラリを InfColorPicker ライブラリに追加する必要があります。
ライブラリを追加するには、次の手順に従います。
Solution Pad の Native References フォルダーを右クリックし、[Add Native References] を選択します。
ここまでに作成したファット バイナリ (
libInfColorPickerSDK.a
) に移動し、[Open] ボタンを押します。ファイルがプロジェクトに含められます。
.a ファイルがプロジェクトに追加されると、Xamarin.iOS によって、ファイルのビルド アクションが ObjcBindingNativeLibrary に自動的に設定され、libInfColorPickerSDK.linkwith.cs
という特殊なファイルが作成されます。
このファイルには、追加したスタティック ライブラリの処理方法を Xamarin.iOS に指示する LinkWith
属性が含まれています。 このファイルの内容は、次のコード スニペットに示されています。
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 に解析し、InfColorPicker プロジェクトの StructsAndEnums.cs
に解析する準備が整いました。
ターミナル アプリに次のコマンドを入力します。
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] は、sharpie xcode -sdks
コマンドで示されるように、インストールした iOS SDK です。 この例では、パラメーターとして *.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 ファイルがディレクトリに作成されます。
上記で作成したバインド プロジェクトで、これらの両方のファイルを開きます。 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 属性を削除する必要があります。 詳細については、検証ガイドを参照してください。
この時点で、バインド プロジェクトが完了し、ビルドする準備が整っているはずです。 バインド プロジェクトをビルドし、最後までエラーが発生しないことを確認しましょう。
バインディングの使用
上記で作成した iOS バインディング ライブラリを使用するサンプル iPhone アプリケーションを作成するには、次の手順に従います。
Xamarin.iOS プロジェクトの作成 - 次のスクリーンショットに示すように、InfColorPickerSample という新しい Xamarin.iOS プロジェクトをソリューションに追加します。
参照のバインド プロジェクトへの追加 - InfColorPickerSample プロジェクトを更新して、InfColorPickerBinding プロジェクトへの参照を含めます。
iPhone ユーザー インターフェイスの作成 - InfColorPickerSample プロジェクトの MainStoryboard.storyboard ファイルをダブルクリックして、これを iOS Designer で編集します。 次に示すように、ボタンをビューに追加して、これに
ChangeColorButton
という名前を付けます。InfColorPickerView.xib の追加 - InfColorPicker Objective-C ライブラリには、.xib ファイルが含まれています。 Xamarin.iOS では、この .xib はバインド プロジェクトに含まれず、そのために、ここで作成するサンプル アプリケーションで実行時エラーが発生します。 この回避策は、Xamarin.iOS プロジェクトに .xib ファイルを追加することです。 Xamarin.iOS プロジェクトを選択し、右クリックして [Add] > [Add Files] を選択し、次のスクリーンショットに示すように .xib ファイルを追加します。
メッセージが表示されたら、.xib ファイルをプロジェクトにコピーします。
次に、Objective-C のプロトコルと、バインドと C# コードでのプロトコルの処理方法を見てみましょう。
プロトコルと Xamarin.iOS
Objective-C では、プロトコルは特定の状況で使用できるメソッド (またはメッセージ) を定義します。 概念的には、これらは C# のインターフェイスによく似ています。 Objective-C プロトコルと C# インターフェイスの主な違いの 1 つは、プロトコルが省略可能なメソッド (クラスが実装する必要がないメソッド) を持てることです。 Objective-C では、@optional キーワードを使用して、省略可能なメソッドを示します。 プロトコルの詳細については、「イベント、プロトコル、デリゲートの」を参照してください。
InfColorPickerController には、次のコード スニペットに示すように、このようなプロトコルが 1 つ含まれています。
@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 アプリケーションでこのインターフェイスを実装する方法は 2 つあります。
- 強力なデリゲート - 強力なデリゲートを使用するには、
InfColorPickerControllerDelegate
をサブクラス化し適切なメソッドをオーバーライドする C# クラスを作成する必要があります。 InfColorPickerController は、このクラスのインスタンスを使用してクライアントと通信します。 - 弱いデリゲート - 弱いデリゲートの手法は少し異なり、一部のクラス (
InfColorPickerSampleViewController
など) でパブリック メソッドを作成し、そのメソッドをExport
属性を介してInfColorPickerDelegate
プロトコルに公開する必要があります。
強力なデリゲートは、Intellisense、型の安全性、優れたカプセル化を提供します。 このような理由から、可能な場所では、弱いデリゲートではなく、強力なデリゲートを使用する必要があります。
このチュートリアルでは、最初に強力なデリゲートを実装し、次に弱いデリゲートを実装する両方の手法について説明します。
強力なデリゲートの実装
強力なデリゲートを使用して Xamarin.iOS アプリケーションを完了し、colorPickerControllerDidFinish:
メッセージに応答します。
サブクラス 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
メソッドをオーバーライドして、InfColorPickerController
の ResultColor
プロパティの値にアクセスします。
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
の背景色を変更できます。
お疲れさまでした。 この時点で、Xamarin.iOS アプリケーションで使用する Objective-C ライブラリが正常に作成され、バインドされました。 次に、弱いデリゲートの使用について説明します。
弱いデリゲートの実装
Xamarin.iOS では、特定のデリゲートの Objective-C プロトコルにバインドされたクラスをサブクラス化する代わりに、NSObject
から派生した任意のクラスにプロトコル メソッドを実装することもでき、メソッドを ExportAttribute
で修飾し、適切なセレクターを指定できます。 この方法を使用する場合は、クラスのインスタンスは、Delegate
プロパティでなく、WeakDelegate
プロパティに割り当てます。 弱いデリゲートを使用すると、デリゲート クラスを別の継承階層に柔軟に移動できます。 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 アプリケーションで使用することに進み、ここでは強力なデリゲートと弱いデリゲートの使用を中心に説明しました。