Cocoa Break Logo Top Soft Develop  脱力空間 Logo
Apple Web Badge
made by mi

概要 翻訳 ソース リンク がらくた

概要 Examples ADC Samples 3rd Parties etc CBOriginals

NumberInput_IMKit_Sample

以下は、Mac OS X 10.5.5 上の Xcode 3.1 で説明しています。このサンプルは、NumberInput 0 から NumberInput 4 までの 5 段階に分かれていて、何もしないものから次第に高度な機能をもつものへと拡張されていきます。

目次:
1 NumberInput 0        2 NumberInput 1        3 NumberInput 2
4 NumberInput 3        5 NumberInput 4        6 更新履歴
1.1 ReadMe の日本語訳
1.2 ビルドとインストール
1.3 グループとファイル
1.4 Info.plist
1.5 main.m
1.6 NumberInputController クラス

1 NumberInput 0

1.1 ReadMe の日本語訳

このプロジェクトは、何も行わない InputMethodKit の入力メソッドを実例で示します。

プロジェクトには、3 つのソースファイルが含まれます。それらは以下のものです。

NumberInputController.h

入力コントローラーを宣言します。新しい InputMethodKit クラスの IMKInputController のサブクラスを作成する Objective-C オブジェクトです。

NumberInputController.m

入力コントローラーを定義します。このインスタンスでは、単一の何も行わないメソッドが定義されています。このメソッドは -(BOOL)inputText:(NSString*)string client:(id)sender で、もともとファイル IMKInputController.h で定義されていたものです( /System/Library/Frameworks/InputMethodKit.framework/Headers/ を見てください)。このメソッドは、キーボード入力を最終的に受けとることになります。このサンプルでは、単に、キーボード入力が利用側に渡されたほうがいいことを意味する NO を返します。

main.m

入力メソッドの進入点 (entry point) を含んでいます。このファイルは、また、IMKServer のインスタンスを割り当てます。サーバーオブジェクトは、NSConnection を通じて利用側アプリケーションと通信します。また、入力メソッドの入力コントローラーオブジェクトの各インスタンスとも通信します。

別の重要なファイルは、Info.plist ファイルです。このファイルには、入力メソッドについての必須情報が含まれていて、それは詳細にコメントされています。ここでどんな情報が提供されているかを調べるために、このファイルを見てください。

ビルドとインストール

単に Xcode でプロジェクトをビルドします。プロジェクトがビルドされた後で、結果のアプリケーションを /Library/Input Methods/ へとドラッグし、ログアウトします。この初期インストールとログアウトの後では、再びログアウトする必要はないはずです。

システム環境設定 (System Preferences) を開いた後、言語環境 (International) を選択し、入力メニュー (Input Menu) タブを選択します。入力メソッドとキーボードレイアウトのリストを目にすることになります。

Number Input という名前の入力メソッドを探し、そのとなりのラジオボタンをクリックします。これで、Number Input 入力メソッドがテキスト入力 (Text Input) メニューへと追加されることになります。

ここで、テキストエディット (TextEdit) アプリケーションを開き、テキスト入力メニューへと行き、NumberInput を選択します。タイプ入力を行ったとき、文字は入力メソッドへと渡されることになり、それはその文字列をログ出力し、NO を返します。

NO を返すことは、入力が処理されず、利用側アプリケーションに渡されたほうがいいことを意味します。コンソール (Console) アプリケーションからログ出力された入力を見ることができます。

これで、何もしない入力メソッドをビルドし、インストールできました。

1.2 ビルドとインストール

ソースを調べていく前に、このサンプルをビルドして動かしてみます。プロジェクトファイルを開いてわかるのが、テキストサービスマネージャーを利用した入力メソッドコンポーネントとは違い、入力メソッドキットを利用した入力メソッドがアプリケーションであるということです。これはターゲット > 情報 > プロパティで、タイプが APPL として指定されていることでもわかりますし、main.m 内で NSApplication が起動されていることでもわかります。そのため、BasicInputMethod の解説で書いたような、コンポーネントに対するリソース設定などは必要ありません。もちろん、情報プロパティリストの設定など、通常のアプリケーションとは違うため、気をつけなければならないことはいくつかあります。

説明は後にして、まずビルドして、動作を調べてみましょう。ReadMe の説明のように、ビルドして、ファイルをドラッグし、ログアウト、または再起動します。ログインした後で、システム環境設定を開き、言語環境 > 入力メニューへと移動すれば、以下のようになっています。KIM は私独自のテキストサービスマネージャー利用入力メソッドなので気にしないでください。自分しか使わないため、BasicInputMethod のアイコンに色を塗って使っていたりします。

上のように、NumberInput を有効にします。そして、テキストエディットアプリケーションを開きます。まず、入力メニューから NumberInput を使うように選択しなければなりません。以下は、選択した後で、再びメニューを開いたときの表示です。キーボードレイアウトを選択した時と同じで、中間に入れられる入力メソッド独自のメニューが何もないことがわかります。

それから、「123456」と入力した後でリターン、「cocoa break」と入力した後でリターンを押します。押した文字がそのまま入力されているのがわかります。同時にコンソールでログ出力が行われているのもわかるでしょう。リターンキーの入力はログ出力されていないことに注意してください。

1.3 グループとファイル

プロジェクトの構成は、以下のようになっています。

クラスファイルは NumberInputController.h と .m で、これは ReadMe で説明されていたとおりです。そして、main.m があり、これがアプリケーションのメイン部分です。

通常とは違うものとしては、Resources の nine.tif、そして Other Frameworks の InputMethodKit.framework があげられます。また、InfoPlist.strings もプロジェクトテンプレートなどの空の状態とは違い、きちんと内容をもっているので注意してください。InputMethodKit.framework は、Linked Frameworks に置かれていませんが、ターゲットの「バンドルをライブラリにリンク」で、Cocoa と InputMethodKit の両方にリンクを行っているので注意してください。

リソースの MainMenu.nib ですが、以下に示すように、このサンプルのものは内容を持っていません。代理オブジェクトのみがあるだけです。

1.4 Info.plist

さて、ReadMe にも書かれていたように、このファイル内に入力メソッドが行うべき設定がいくつかあります。それにコメントが付けられていますが、Xcode のデフォルトでは、このファイルは XMLPropertyList として、キーと値の表として表示されてしまい、コメントが見られません。環境設定 > ファイルタイプ で、text.plist を Plain text file(標準テキストファイル)とすることで、Xcode 内でこのファイルをテキストとして見ることができます。ただし、この設定をする前に、ファイルを見ていた場合、キャッシュが残ったままなので、環境設定を変えても表示が変わりません。一度、プロジェクトを閉じて、再び開く必要があります。一時的にだけ見たいなら、外部のテキストエディタを使って、このファイルを開いたり編集するといいでしょう。デフォルトのプロパティリスト表示は以下のようになります。

テキストエディタで開いた場合は、以下のようになります。不要な部分は省いています。

Info.plist
<dict> <key>CFBundleDevelopmentRegion</key> // 開発言語 <string>English</string> <key>CFBundleExecutable</key> // 実行可能形式名 <string>NumberInput</string> <key>CFBundleIconFile</key> // アイコンファイル <string></string> <key>CFBundleIdentifier</key> // バンドル識別子 <string>com.yourcompany.inputmethod.NumberInput</string> <key>CFBundleInfoDictionaryVersion</key> // 情報ディクショナリバージョン <string>6.0</string> <key>CFBundleName</key> // バンドル名 <string>«PROJECTNAME»</string> <key>CFBundlePackageType</key> // バンドルパッケージタイプ <string>APPL</string> <key>CFBundleSignature</key> // バンドルシグニチャ <string>????</string> <key>CFBundleVersion</key> // バンドルバージョン <string>1.0</string> <key>NSMainNibFile</key> // 主要 nib ファイル <string>MainMenu</string> <key>NSPrincipalClass</key> // 主要クラス <string>NSApplication</string> <!-- --> <!-- InputMethodKit にもとづく入力メソッドの必須項目のはじまり --> <!-- --> <!-- Input Methods はバックグラウントのみのアプリケーション --> <key>LSBackgroundOnly</key> // バックグラウンドのみかどうか <string>1</string> <!-- --> <!-- InputMethodConnectionName が指定されなければならない --> <!-- この文字列は、それを通じて入力メソッドとしてサービスが発行される接続に命名する。 --> <!-- InputMethodKit はテキスト入力を配送するための接続 --> <!-- を管理する NSConnection を作るのにこの名前を使うことになる。 --> <key>InputMethodConnectionName</key> // 入力メソッド接続名 <string>NumberInput_1_Connection</string> <!-- --> <!-- 次の手順は、入力コントローラークラスを指定すること --> <!-- InputMethodKit は、InputMethodServerControllerClass キーでバンドルを探す --> <key>InputMethodServerControllerClass</key> // 入力コントローラークラス <string>NumberInputController</string> <!-- --> <!-- アイコンファイル指定。言語環境の入力メニューパネル内で入力メソッドを表示するのに使用される。 --> <key>tsInputMethodIconFileKey</key> // 入力メソッドアイコンファイル <string>nine.tiff</string> <!-- --> <!-- 次の必須項目は、入力メソッドの文字範囲。 --> <!-- これは ISO 言語コードの配列 --> <!-- これらのコードは、入力メソッドをユーザーに対して区分する助けとなる。 --> <key>tsInputMethodCharacterRepertoireKey</key> // 文字範囲 <array> <string>Latn</string> // ラテン </array> <!-- --> <!-- 必須項目の終わり --> <!-- --> </dict>

最初のほうの項目は、通常のアプリケーションと同じですす。表の表示と、テキスト内容を比べてみてください。Xcode 内での表示は、各キーの名前ではなく意味を示していることがわかります。途中のコメントから以降が入力メソッドに必須の項目になります。

最初の LSBackgroundOnly は、バックグラウンド専用アプリケーションであること意味します。これを指定すれば、ユーザーインターフェースは一切表示できません。以前のテキストサービスコンポーネントでは、サーバーアプリケーションの情報プロパティリストで、これを設定していました。パレット等を表示する場合は、LSUIElement を指定することで、パレットを表示していました。ネット等で、入力メソッドキット使用の場合は、サーバーは LSBackgroundOnly でないとダメという情報を目にしましたが、LSUIElement で動作しないのか確かめていませんので真偽は不明です。いずれ確認してみたいと思います。

以降は、接続のための NSConnection で使われる名前、入力コントローラークラス、アイコンファイル、文字範囲です。この文字範囲は、以前のコンポーネントでは、リソース内やコードで指定していたものです。今回も、情報プロパティリストの指定と、メソッドによって返される値が別々になっているようです。前者はシステム環境設定等で使われるもので、後者は実際に利用するアプリケーションなどから問い合わされるものです。

コメントもあるため、十分理解できると思うので、情報プロパティリストについてはこのぐらいにして、さっそくソースを見てみましょう。まずは、メインの部分である main.m です。

1.5 main.m

main.m では main 関数が定義されています。これが、実行可能形式の進入点になります。main 関数の前に、変数等が設定されているので、まずそちらを見てみます。

main.m > main より前の部分
// 各入力メソッドは、一意的な接続名を必要とする。 // 接続名ではピリオドと空白が許可されないことに注意 const NSString* kConnectionName = @"NumberInput_1_Connection"; // アプリケーションコントローラーの委任が簡単にアクセスできるようグローバルにしている IMKServer* server;

さて、最初に接続名が定義されています。これは情報プロパティリストにあったものと同じですが、コード内で使えるように、定数文字列として確保しています。

つぎに、グローバル変数としてサーバーを宣言しています。コメントにもあるようにアクセスを簡単にするためです。

いよいよ、main 関数です。どうなっているのでしょうか。それを見る前に、参考として Cocoa アプリケーションの新規プロジェクトテンプレートにおける main 関数がどんな風であるか見てみます。

Cocoa アプリケーションテンプレートの main 関数
int main(int argc, char *argv[]) { return NSApplicationMain(argc, (const char **) argv); }

この関数内では、アプリケーションオブジェクトを作成し、主要 nib ファイルを読み込み、アプリケーションを実行しています。では、このサンプルの main 関数を見てみましょう。

main.m > main
int main(int argc, char *argv[]) { NSString* identifier; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // バンドル識別子を見つけて、入力メソッドサーバーを初期化 identifier = [[NSBundle mainBundle] bundleIdentifier]; // 次の文で使われていない… server = [[IMKServer alloc] initWithName:(NSString*)kConnectionName bundleIdentifier:[[NSBundle mainBundle] bundleIdentifier]]; // この場合、入力メソッドはバックグラウンド専用アプリケーションなのでバンドルを明示的に読み込む [NSBundle loadNibNamed:@"MainMenu" owner:[NSApplication sharedApplication]]; // 最後にすべてを走らせる [[NSApplication sharedApplication] run]; [pool release]; return 0; }

まず最初に、自動解放プールが作られていることに注意してください。Foudation ツールを含む、Cocoa 利用アプリケーションでは、NSApplicationMain 関数を使わないで、自分で main 関数を書くなら、必ずこれを最初に行います。自動解放オブジェクトは、Cocoa メソッド内で内部的に使われたりしている可能性もあるため、Cocoa メソッドを呼ぶ前に必ず自動解放プールを 1 つ作っておき、終了前にそれを解放します。これは、通常の Cocoa アプリケーションと同じ手順です。

つぎに自身の主要バンドルのバンドル識別子を取得しています。これは、次の初期化メソッドで必要になるためです。ただし、次の文で identifier を使っていません。使うように変更するか、逆に identifier の宣言と取得行を除去して OK です。それから、先ほど説明したグローバル接続名を使って、サーバーオブジェクトを初期化します。この初期化メソッド内で、指定されたバンドルの情報プロパティリストを使って、サーバーを初期化することになります。利用される項目は、先ほど Info.plist で説明した必須項目にあたるもので、このためにも情報プロパティリストを設定することが必要だったわけです。ここで名前には、接続名と同じものが使われていますが、接続に利用する名前は情報プロパティリストで指定されていますので、同じものである必要はありません。

つぎに、主要 nib ファイルを読み込んでいます。コメントにあるとおり、通常は自動で読み込まれますが、この場合バックグラウンド専用なので、明示的に読み込む必要があります。

最後に、アプリケーションを実行しています。他のアプリケーションで入力メソッドの要求があったとき、最初に作られたサーバーインスタンスがそれに応答し、個別のセッションごとに、入力コントローラーインスタンスを作って、それを使うことになります。テキストサービスコンポーネントでは、他アプリケーション内で読み込まれるコンポーネントという形でした。入力メソッドコントローラーも、接続を通じてサーバーと通信する形になっていますので、他アプリケーション内に内部的なコンポーネントが入力コントローラークラスをベースにして作られているのかもしれません。

さて、次に個別の要求の際に作られる、入力コントローラークラスを見てみましょう。

1.6 NumberInputController クラス

まずヘッダファイルを見てみます。これは非常に簡単です。

NumberInputController.h
@interface NumberInputController : IMKInputController { } @end

このように、NumberInputController クラスは、IMKInputController のサブクラスとして宣言されています。インスタンス変数がなく、継承メソッド以外のメソッドを定義していないので、内容は空になっています。

つぎに、実装ファイルを見てみましょう。まず、クラスの実装宣言があり、その下にコメントが付けられています。これは IKMServerInput プロトコルリファレンスで説明されていることと同じです。リファレンスの翻訳を見てください。簡単にまとめると、IKMServerInput プロトコルでテキスト入力を受けとって処理するのに、キーバインディングを使う方法(このサンプル)、テキストデータのみ、すべてのイベントを処理、という 3 つの方法があるということです。

ここでは、最初の方法を使っていて、この方法では、didCommandBySelector:client:inputText:client: を使います。システムがキー入力を受けとったら、キーダウンイベントを入力メソッドが実装するアクションメソッドへと対応付けようとします。見つかった場合、didCommandBySelector:client: が呼ばれ、見つからなかったら inputText:client: が呼ばれます。このサンプルでは、文字入力を処理する後者だけが実装されています。

NumberInputController.m > inputText:client:
-(BOOL)inputText:(NSString*)string client:(id)sender { // キー入力が受けとられ処理されたことを示すには YES を返す。キー処理は、この場合継続されない。 // 別の言い方をすれば、システムはキーダウンイベントをアプリケーションへとは配送しなくなる。 // NO を返せば、元のキーダウンイベントが利用側へと渡されることになる。 NSLog(@"%@", string); return NO; }

このメソッドでは、単に入ってきた文字をログ出力しているだけです。コメントにもあるように、キーダウンイベントがそのまま渡されるように NO を返しています。「ビルドとインストール」の画像で、コンソールを示しましたが、あの出力はこのメソッドからなされていたものです。このメソッドが呼ばれていることが確認できます。

これで、このサンプルの最初のものについては、ほぼわかったと思います。InfoPlist.strings は説明していませんが、通常のアプリケーションでローカル化のために使われるものとほぼ同じなので、説明していません。実際には他にモード名などのローカル化もありますが、サンプルのこの段階では使われないため、説明を省きました。

入力メソッドとは言っても、サンプルのこの段階では何も行っていません。そのため、ビルドやインストールを行っても、入力メソッドという実感がないかもしれません。次の段階から、じょじょに機能が増やされていきます。(以下、次ファイルへと続く。)


 次へ

管理人:神吉 秀典 E-mail:puer@ba.wakwak.com