Google Chrome Mac版の最新バージョン (3.0.194.3) がリリースされました。変更点はこちらを参照いただくとして、着実に改良が進められているようですね。マイコミジャーナルのトップページが正しく表示されないことからも明らかなように、問題点は多々ありますが、その"勢い"は要注目だろうと思います。

さて、今回は「サービス」について。存在は知っているが使ったことはない、なくてもさほど困らないという声も聞こえる地味な存在ではあるものの、なかなか味わい深い機能を備えている。Snow Leopardで機能強化が予定されているが、ここでは現時点における機能とちょっとしたTIPSを紹介してみよう。

「サービス」の仕組み

「サービス」は、Mac OS Xにおけるアプリケーション間通信機能の一種。そもそもはNeXTSTEPの時代に実装され、基本クラスのFoundationが「Cocoa」の主要部分としてOS Xに採用されたことから、大きな変更のないまま現在のLeopardに継承されている。

その特徴は、「ペーストボード」を介したデータの授受にある。サービスに対応したアプリケーションは、メニューバーのアプリケーション名 (Safari.appならば「Safari」) 項目以下にある「サービス」サブメニュー以下に、各種アクションが表示される。適当なアクションを選択すると、データはペーストボードを介して、そのアクションを提供するアプリケーションにデータが渡され (または呼び出され)、アクションとして定義された処理が行われるという流れだ。

Safariとテキストエディットを例に説明してみよう。Safari上で文章を範囲指定し、[Safari] - [サービス] - [テキストエディット] - [選択部分を含む新しいウインドウを開く]を選択する。この作業で (テキストエディットが提供する) サービスが実行され、Safariで範囲指定された文章がテキストエディットの新規ウインドウとして開かれる。アプリケーションの起動もあわせて処理されるため、事前にテキストエディットを起動しておく必要がないところがポイントだ。

Safariからサービス経由でテキストエディットにデータを渡したところ。コピー&ペーストしたときとの動作の違いを試してほしい

サービスには「プロセッサ型」と「プロバイダ型」の2種類があり、前者はデータをプッシュし、後者はデータをプルする。前述したSafariからTextEditへという流れは、プロセッサ型に分類される。プロバイダ型は、テキストエディットやスティッキーズからグラブ (Grab.app) を呼び出し編集中の文書へスクリーンショットを挿入させることが、典型的なパターンだろう。

このサービスを実装することは、さほど手間ではない。Cocoaの場合、システムに登録する処理とサービスに応答するためのメソッドを実装する程度でプログラミングは完了する。そしてアプリケーションバンドル内にあるInfo.plistへ、サービス機能がある旨の情報を記述しておけば、システムが自動的に当該アプリケーションのサービスを検出 (Leopardではどのフォルダも検出対象)、サービスメニューへ表示してくれる。反対にアプリケーションを削除すれば、サービスメニューからそのアプリケーションの提供するサービスが表示されなくなるしくみだ。

サービスを手動で更新する

サービスはコツをつかめば便利に使えるが、メニューを更新するためにはいちどログアウトし、再びログインしなければならない。多数のアプリケーションをインストールしているとき、どのメニューがどのアプリケーションに対応するのかわからない、そこでいちどアプリケーションを削除して再ログインしてみよう、などと考えると、徒に時間を費やすことになる。サービスを実装したアプリケーションの動作テストを行うときには、イライラすること確実だ。

サービスメニューは「NSUpdateDynamicServices()」をコールするだけで再構築できるのだが、この機能を持つアプリケーション / コマンドが存在しない -- NeXTのときにはmake_servicesというコマンドがあったがいつからか消えた -- ため、自力で用意してみた (リスト1)。適当なテキストエディタにコピー&ペーストし、「refresh.m」というファイル名で保存したあと、以下のコマンドラインを実行してほしい (Developer Tools要)。カレントディレクトリに同名のコマンドが生成されるので、それを実行すれば再ログインもアプリケーションの再起動もすることなく、サービスメニューを再構築できる。

$ gcc refresh.m -o refresh -framework Cocoa
$ ./refresh

リスト1: サービスメニュー更新用プログラムのソースコード

#import <Cocoa/Cocoa.h>

int main (){
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    NSUpdateDynamicServices();
    printf("Now, the services menu has been refreshed! \n");
    [pool release];
    return 0;
}

10行にも満たない単純なプログラムだが、サービスの動作確認を行うときは重宝するかも

ところで、この「サービス」、次のSnow Leopardでは機能強化が予定されている。システム上に存在するすべてのメニューを表示する現在のスタイルではなく、アプリケーションに合わせてメニューが表示されるようになるため、どのアクションを実行すればいいか迷うことが少なくなる。Automatorを使い、カスタムサービスを作成することも可能になるという。NeXSTEP / OPENSTEPから移行して以来おそらく初の大変更、楽しみに待ちたいと思う。