アプリからUNIXコマンドを実行する。
非同期にバックグラウンドで実行する例として、topコマンドを実行してみる。
-stopProcess:で停止するまで、ターミナルでの実行と同様にシステムの情報を更新し続けます。
Objective-C
// タスクの開始
- (IBAction)startProcess:(id)sender
{
// _taskはメンバ変数
_task = [[NSTask alloc] init];
// 標準出力
NSPipe *outPipe = [NSPipe pipe];
[_task setStandardOutput:outPipe];
// 標準エラー
NSPipe *errPipe = [NSPipe pipe];
[_task setStandardError:errPipe];
[_task setLaunchPath:@"/usr/bin/top"];
[_task setArguments:[NSArray arrayWithObjects: @"-s", @"1", @"-l", @"3600", @"-stats", @"pid,cpu,time,command", nil]];
// 標準出力のデータが準備できたことを通知
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(getData:)
name:NSFileHandleReadCompletionNotification
object:[outPipe fileHandleForReading]];
[[outPipe fileHandleForReading] readInBackgroundAndNotify];
// タスクの終了が完了したことを通知
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(taskExited:)
name:NSTaskDidTerminateNotification
object:_task];
// タスクの実行開始
[_task launch];
}
Objective-C
// タスクの停止
- (IBAction)stopProcess:(id)sender
{
// Notificationの削除
[[NSNotificationCenter defaultCenter] removeObserver:self
name:NSFileHandleReadCompletionNotification
object:[[_task standardOutput] fileHandleForReading]];
// タスクの停止
// 停止の完了を待たずに、すぐに処理が戻ってくる。
[_task terminate];
// タスクが完全に終了するのを待つ場合は以下を実行。
// NSTaskDidTerminateNotification の通知を待って非同期で終了処理をする事も可。
[_task waitUntilExit];
}
Objective-C
// 標準出力の読み出し
- (void)getData:(NSNotification *)aNotification
{
NSData *data = [[aNotification userInfo] objectForKey:NSFileHandleNotificationDataItem];
if (data != nil && [data length])
{
// 例:NSTextViewに表示してみる
[_textView setString:[[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease]];
// we need to schedule the file handle go read more data in the background again.
[[aNotification object] readInBackgroundAndNotify];
}
else
{
[self stopProcess:nil];
}
}
Objective-C
// タスクが完了した場合の後処理
- (void)taskExited:(NSNotification *)aNotification
{
[[NSNotificationCenter defaultCenter] removeObserver:self
name:NSTaskDidTerminateNotification
object:_task];
[_task release];
_task = nil;
}