タイトル鶴薗賢吾のCocoaはやっぱり!出張版》7. UNIXコマンドの実行(5)カテゴリーCocoa, 鶴薗賢吾のCocoaはやっぱり!出張版
作成日2002/1/22 1:58:59作成者新居雅行
◎ コマンドの実行結果の受け取り
これで通知が発生するようになりましたので、実行したコマンドからの出力の受け取りの方法について説明します。先程、通知が発生した時に呼び出されるメソッドに指定したgetData : を見ていきます。通知を受けるメソッドは、必ずNSNotificationクラスのパラメータを1つ持たなければなりませんので以下のようになっています。

// ソース:MoriarityController.m/メソッド:getData

- (void) getData : (NSNotification *) aNotification {

// 出力されたデータを取得
NSData *data = [ [ aNotification userInfo ]
objectForKey : NSFileHandleNotificationDataItem ];

if ( [ data length ] ) { // 文字列に変換して出力
[ controller appendOutput :
[ [ [ NSString alloc ] initWithData : data
encoding : NSUTF8StringEncoding ]
autorelease ] ];
} else {
[ self stopProcess ]; // データがとれなくなったら終了
}

if ( task ) { // タスクがある時は、再度、通知を発行してもらう
[ [ aNotification object ] readInBackgroundAndNotify ];
}
else { // タスクがなくなっていたら終了 ( エラー処理 )
[ self stopProcess ];
}
}

通知から出力データを取り出すにはuserInfoメソッドを使います。このuserInfoメソッドの返り値は辞書になっています ( 通知の種類によっては沢山の情報を持っているため ) ので、辞書からobjectForKey : メソッドを使って出力結果を取り出します。辞書から取り出すためのキーはNSFileHandleNotificationDataItemです。これで、UNIXコマンドが出力したデータがNSDataクラスとして得られるので、これを文字列に変換してappendOutput : メソッドを使って、コントローラに出力します。

 ★ NSNotification : 通知に添付されているデータを取得
  [書式] - (NSDictionary *) userInfo
  [出力] 返り値 : 通知に添付されているデータのインスタンス。
          データがない場合はnilが返る。

 ★ NSNotification : 通知の名前を取得
  [書式] - (NSString *) name
  [出力] 返り値 : 通知の名前。

 ★ NSNotification : 通知に関連するインスタンスを取得
  [書式] - (id) object
  [入力]
  [出力] 返り値 : 通知に関連するインスタンス。通知を行ったインスタンス
          のことが多いが、通知に依存する。インスタンスが無い
          場合はnilが返る。

データが取れなくなってデータ長が0になったら終了処理を行います。そうでない場合は、再度ファイルハンドルに対して通知発行を依頼して、次の通知を待ちます。

続いては、コマンド実行中に、Stopボタンを押された場合の処理です。sleuth : メソッド経由でstopProcessメソッドが呼ばれます。ここでは、コントローラの終了処理を行った後、オブザーバの削除とコマンドの中止を行っています。

// ソース:MoriarityController.m/メソッド:stopProcess

- (void) stopProcess {

[ controller processFinished ]; // コントローラー終了処理
controller = nil;

// オブザーバー削除
[ [ NSNotificationCenter defaultCenter ]
removeObserver : self
name : NSFileHandleReadCompletionNotification
object : [ [ task standardOutput ] fileHandleForReading ] ];

[ task terminate ]; // コマンド実行中止

}

 ★ NSNotificationCenter : オブザーバーの削除
  [書式] - (void) removeObserver : (id ) anObserver
          name : (NSString *) notificationName
          object : (id ) anObject
  [入力] anObserver : 削除するオブザーバのインスタンス。
     name : 削除する通知の種類。nilにすると全ての通知を解除する。
     object : 削除する通知の発信先の指定。nilにすると全てのインス
          タンスの通知を解除する。

 ★ NSTask : 実行時を中止
  [書式] - (void) terminate

コマンドの実行を一時停止する機能もあります。suspendで一時停止、resumeで実行再開です。suspendを複数回実行した場合は、同じ回数resumeをすることで初めて実行が再開されます。

 ★ NSTask : 実行を一時停止
  [書式] - (BOOL) suspend
  [出力] 返り値 : 成功 - YES、失敗 - NO ( 実行されていない時など )
  [備考] 複数回実行可能で、同回数のresumeで実行が再開される。

 ★ NSTask : 実行を再開
  [書式] - (BOOL) resume
  [出力] 返り値 : 成功 - YES、
        失敗 - NO ( 実行されていない、suspendされていない時など )
  [備考] suspendと同回数実行すると再開される。

――――まとめ
以上のようにCocoaアプリケーションからは比較的簡単にUNIXのコマンドを呼び出すことが出来ます。UNIXのコマンドの中には便利なものも多いですし、既存のUNIXコマンドにGUIを付けて使いやすくすることもできるわけです。

また、Cocoaアプリケーションはパッケージ形式になっていて、色んなファイルをアプリケーションの中に閉じ込めておくことが出来ますので、今までと違った開発スタイルを採ることも出来ます。パッケージの中にUNIXのコマンドだけでなく、perlのスクリプトファイルを閉じ込めておいてperlを起動してスクリプトを実行させることも簡単です。

Cocoaを使って、UNIXのパワフルなアプリケーションに、Mac OSの使いやすさを付加したアプリケーションを作るというのも、これからの新しいスタイルとなるでしょう。
(この項、以上)
[鶴薗賢吾]
関連リンクCocoaはやっぱり!