チュートリアル - 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 表現に基づいて色を選択でき、より見やすくなる色選びにできます。

Example of the InfColorPicker library running on iOS

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 コマンド ライン ツール (具体的には makelipo) を使用します。 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
    
    • 次のように、コマンド ライン ツールをインストールするように求められ、[Install] ボタンを選択します。Installing the command line tools

    • ツールは、次のように Apple のサーバーからダウンロードされてインストールされます。Downloading the tools

  • Apple 開発者向けのダウンロード - コマンド ライン ツール パッケージは、Apple 開発者向けのダウンロード Web ページで入手できます。 Apple ID でログインし、次のようにコマンド ライン ツールを検索してダウンロードします。Finding the Command Line Tools

コマンド ライン ツールがインストールされたので、チュートリアルを続行する準備ができました。

チュートリアル

このチュートリアルでは、次の手順について説明します。

  • スタティック ライブラリの作成 - この手順では、InfColorPickerObjective-C コードのスタティック ライブラリを作成します。 スタティック ライブラリはファイル拡張子 .a を持ち、ライブラリ プロジェクトの .NET アセンブリに埋め込まれます。
  • Xamarin.iOS バインド プロジェクトの作成 - スタティック ライブラリを作成したら、それを使用して Xamarin.iOS バインド プロジェクトを作成します。 バインド プロジェクトは、先ほど作成したスタティック ライブラリと、Objective-C API を使用する方法を説明する C# コードの形式のメタデータで構成されます。 このメタデータは、一般に API 定義と呼ばれます。 Objective Sharpie を使用して、API 定義の作成に役立てます。
  • API 定義の正規化 - Objective Sharpie には役立つ優れた機能がありますが、何でもしてくれるわけではありません。 API 定義を使用する前に行う必要があるいくつかの変更について説明します。
  • バインド ライブラリの使用 - 最後に、Xamarin.iOS アプリケーションを作成して、新しく作成したバインド プロジェクトの使用方法を示します。

関連する手順を理解したので、チュートリアルの残りの部分に進みましょう。

スタティック ライブラリの作成

Github で InfColorPicker のコードを調べる場合:

Inspect the code for InfColorPicker in Github

プロジェクトには、次の 3 つのディレクトリが表示されます。

  • InfColorPicker - このディレクトリには、プロジェクト用の Objective-C コードが格納されています。
  • PickerSamplePad - このディレクトリには、サンプルの iPad プロジェクトが格納されています。
  • PickerSamplePhone - このディレクトリには、サンプルの iPhone プロジェクトが格納されています。

GitHub から InfColorPicker プロジェクトをダウンロードし、選択したディレクトリに解凍してみましょう。 PickerSamplePhone プロジェクトの Xcode ターゲットを開くと、Xcode ナビゲーターに次のプロジェクト構造が表示されます。

The project structure in the Xcode Navigator

このプロジェクトでは、InfColorPicker ソース コード (赤いボックス内) を各サンプル プロジェクトに直接追加することで、コードの再利用を実現します。 サンプル プロジェクトのコードは青いボックス内にあります。 この特定のプロジェクトではスタティック ライブラリが提供されないため、スタティック ライブラリをコンパイルする Xcode プロジェクトを作成する必要があります。

その最初の手順では、InfoColorPicker ソース コードをスタティック ライブラリに追加します。 これを実現するには、次の操作を行います。

  1. Xcode を起動します。

  2. [File] メニューで [New]>[Project] を選択します。

    Screenshot shows Project selected from the New menu of the File menu.

  3. [Framework & Library][Cocoa Touch Static Library] テンプレートを選択し、[Next] ボタンを選択します。

    Select the Cocoa Touch Static Library template

  4. [Project Name] に「InfColorPicker」と入力し、[Next] ボタンをクリックします。

    Enter InfColorPicker for the Project Name

  5. プロジェクトを保存する場所を選択し、[OK] ボタンを選択します。

  6. 次に、InfColorPicker プロジェクトのソースをスタティック ライブラリ プロジェクトに追加する必要があります。 InfColorPicker.h ファイルはスタティック ライブラリに既に存在するため (既定)、Xcode では上書きできません。 [Finder] から、GitHub から解凍した元のプロジェクトの InfColorPicker ソース コードに移動し、すべての InfColorPicker ファイルをコピーして、新しいスタティック ライブラリ プロジェクトに貼り付けます。

    Copy all of the InfColorPicker files

  7. Xcode に戻り、InfColorPicker フォルダーを右クリックし、[Add files to "InfColorPicker..."] を選択します。

    Adding files

  8. [Add Files] ダイアログ ボックスで、先ほどコピーした InfColorPicker ソース コード ファイルに移動し、すべてを選択して、[Add] ボタンをクリックします。

    Select all and click the Add button

  9. ソース コードがプロジェクトにコピーされます。

    The source code will be copied into the project

  10. Xcode プロジェクト ナビゲーターから InfColorPicker.m ファイルを選択し、最後の 2 行をコメント アウトします (このライブラリの記述方法のため、このファイルは使用されません)。

    Editing the InfColorPicker.m file

  11. ライブラリに必要なフレームワークがあるかどうかを確認する必要があります。 この情報は、README で、または提供されているサンプル プロジェクトのいずれかを開いて確認できます。 この例では、Foundation.frameworkUIKit.frameworkCoreGraphics.framework を使用するので、それらを追加しましょう。

  12. [InfColorPicker target] > [Build Phases] を選択し、[Link Binary With Libraries] セクションを展開します。

    Expand the Link Binary With Libraries section

  13. + ボタンを使用してダイアログを開き、上記の必要なフレームのフレームワークを追加できます。

    Add the required frames frameworks listed above

  14. [Link Binary With Libraries] セクションは、次の図のようになります。

    The Link Binary With Libraries section

この時点で完了に近付いていますが、まだ終わってはいません。 スタティック ライブラリは作成されましたが、これをビルドして、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 バインド プロジェクトの将来のメンテナンスとサポートが簡略化されます。

このようなタスクを自動化するために使用できるツールは多数あります。シェル スクリプト、rakexbuild、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 スタティック ライブラリと同じ場所にファイルを保存します。

Save the file with the name Makefile

Mac でターミナル アプリケーションを開き、メイクファイルの場所に移動します。 ターミナルに「make」と入力し、Enter キーを押すと、メイクファイルが実行されます。

Sample makefile output

make を実行すると、テキストのスクロールが多数表示されます。 すべてが正常に機能した場合は、BUILD SUCCEEDED という文が表示され、libInfColorPicker-armv7.a ファイル、libInfColorPicker-i386.a ファイル、libInfColorPickerSDK.a ファイルがメイクファイルと同じ場所にコピーされます。

The libInfColorPicker-armv7.a, libInfColorPicker-i386.a and libInfColorPickerSDK.a files generated by the Makefile

次のコマンドを使用して、ファット バイナリ内のアーキテクチャを確認できます。

xcrun -sdk iphoneos lipo -info libInfColorPicker.a

これにより、次の内容が表示されます。

Architectures in the fat file: libInfColorPicker.a are: i386 armv7 x86_64 arm64

この時点で、Xcode と Xcode コマンド ライン ツール makelipo を使用してスタティック ライブラリを作成し、iOS バインドの最初の手順を完了しました。 次の手順に進み、Objective-Sharpie を使用して、API バインドの作成を自動化しましょう。

Xamarin.iOS バインド プロジェクトの作成

Objective-Sharpie を使用してバインド プロセスを自動化するには、API 定義 (Objective-Sharpie を使用してビルドに役立てる) を格納する Xamarin.iOS バインド プロジェクトを作成し、C# バインディングを作成する必要があります。

次の操作を行います。

  1. Visual Studio for Mac を起動します。

  2. [File] メニューで、[New]>[Solution] を選択します。

    Starting a new solution

  3. [New Solution] ダイアログ ボックスで、[Library]>[iOS Binding Project] を選択します。

    Select iOS Binding Project

  4. [次へ] をクリックします。

  5. [Project Name] に「InfColorPickerBinding」と入力し、[Create] ボタンをクリックしてソリューションを作成します。

    Enter InfColorPickerBinding as the Project Name

ソリューションが作成され、2 つの既定のファイルが含まれます。

The solution structure in the Solution Explorer

  • ApiDefinition.cs - このファイルに、Objective-C API を C# でラップする方法を定義するコントラクトが含まれます。
  • Structs.cs - このファイルに、インターフェイスとデリゲートに必要なすべての構造体または列挙値が保持されます。

このチュートリアルの後半で、これら 2 つのファイルを操作します。 まず、InfColorPicker ライブラリをバインド プロジェクトに追加する必要があります。

バインド プロジェクトにスタティック ライブラリを含める

これで基本バインド プロジェクトの準備ができたので、上記で作成したファット バイナリ ライブラリを InfColorPicker ライブラリに追加する必要があります。

ライブラリを追加するには、次の手順に従います。

  1. Solution Pad の Native References フォルダーを右クリックし、[Add Native References] を選択します。

    Add Native References

  2. ここまでに作成したファット バイナリ (libInfColorPickerSDK.a) に移動し、[Open] ボタンを押します。

    Select the libInfColorPickerSDK.a file

  3. ファイルがプロジェクトに含められます。

    Including a file

.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 ファイルがディレクトリに作成されます。

The InfColorPicker.enums.cs and InfColorPicker.cs files

上記で作成したバインド プロジェクトで、これらの両方のファイルを開きます。 InfColorPicker.cs ファイルの内容をコピーし、ApiDefinition.cs ファイルに貼り付けて、既存の namespace ... コード ブロックを InfColorPicker.cs ファイルの内容に置き換えます (using ステートメントはそのまま残します)。

The InfColorPickerControllerDelegate file

API 定義の正規化

Objective Sharpie では、Delegates の変換に問題が発生する場合があるため、InfColorPickerControllerDelegate インターフェイスの定義を変更し、[Protocol, Model] 行を次のように置き換える必要があります。

[BaseType(typeof(NSObject))]
[Model]

そのため、定義は次のようになります。

The definition

次に、InfColorPicker.enums.cs ファイルの内容を同様にコピーし、StructsAndEnums.cs ファイルに貼り付け、using ステートメントはそのまま残します。

The contents the StructsAndEnums.cs file

また、Objective Sharpie がバインディングに [Verify] 属性で注釈を付ける場合もあります。 これらの属性は、バインディングと元の C/Objective-C 宣言 (これはバインドされた宣言の上のコメント内に表示されます) を比較することで、Objective Sharpie が正しい処理を実行したことを自分で "検証" する必要があることを意味します。 バインドを確認したら、verify 属性を削除する必要があります。 詳細については、検証ガイドを参照してください。

この時点で、バインド プロジェクトが完了し、ビルドする準備が整っているはずです。 バインド プロジェクトをビルドし、最後までエラーが発生しないことを確認しましょう。

バインド プロジェクトのビルドと、エラーがないことの確認

バインディングの使用

上記で作成した iOS バインディング ライブラリを使用するサンプル iPhone アプリケーションを作成するには、次の手順に従います。

  1. Xamarin.iOS プロジェクトの作成 - 次のスクリーンショットに示すように、InfColorPickerSample という新しい Xamarin.iOS プロジェクトをソリューションに追加します。

    Adding a Single View App

    Setting the Identifier

  2. 参照のバインド プロジェクトへの追加 - InfColorPickerSample プロジェクトを更新して、InfColorPickerBinding プロジェクトへの参照を含めます。

    Adding Reference to the Binding Project

  3. iPhone ユーザー インターフェイスの作成 - InfColorPickerSample プロジェクトの MainStoryboard.storyboard ファイルをダブルクリックして、これを iOS Designer で編集します。 次に示すように、ボタンをビューに追加して、これに ChangeColorButton という名前を付けます。

    Adding a Button to the view

  4. InfColorPickerView.xib の追加 - InfColorPicker Objective-C ライブラリには、.xib ファイルが含まれています。 Xamarin.iOS では、この .xib はバインド プロジェクトに含まれず、そのために、ここで作成するサンプル アプリケーションで実行時エラーが発生します。 この回避策は、Xamarin.iOS プロジェクトに .xib ファイルを追加することです。 Xamarin.iOS プロジェクトを選択し、右クリックして [Add] > [Add Files] を選択し、次のスクリーンショットに示すように .xib ファイルを追加します。

    Add the InfColorPickerView.xib

  5. メッセージが表示されたら、.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 メソッドをオーバーライドして、InfColorPickerControllerResultColor プロパティの値にアクセスします。

ColorSelectedDelegate のインスタンスの作成 - イベント ハンドラーには、前の手順で作成した ColorSelectedDelegate 型のインスタンスが必要です。 InfColorPickerSampleViewController クラスを編集し、次のインスタンス変数をこのクラスに追加します。

ColorSelectedDelegate selector;

ColorSelectedDelegate 変数の初期化 - selector が有効なインスタンスであることを確認するには、ViewControllerViewDidLoad メソッドを、次のスニペットに一致するように更新します。

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 の背景色を変更できます。

Running the Application

お疲れさまでした。 この時点で、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 アプリケーションで使用することに進み、ここでは強力なデリゲートと弱いデリゲートの使用を中心に説明しました。