2

そのため、NSTaskを使用して、何かのリストを生成するスクリプトをtxtに生成し、そこから読み取ります。しかし、現在のコード(下記)を使用すると、NSTaskが終了する前にアラートがポップアップするため、アラートが空白になります。試しましwaitUntilExitたが、このアクションを呼び出すボタンがフリーズしますが、UIがロックされません。

- (void) runSupported {
    stask = [[NSTask alloc] init];
    [stask setLaunchPath:@"/bin/bash"];
    NSString *script;
    script = [[[NSBundle mainBundle] bundlePath] stringByAppendingString:@"/apps.sh"];
    NSArray *sargs = [NSArray arrayWithObjects:script, @"-txt", nil];
    [stask setArguments: sargs];
    [stask launch];

    NSString *apps;
    apps = [NSString stringWithContentsOfFile:@"/var/mobile/supported.txt" encoding:NSUTF8StringEncoding error:nil];
    NSFileManager *fm = [NSFileManager defaultManager];
    if ([fm fileExistsAtPath:apps]) {
        UIAlertView *supported = [[UIAlertView alloc] initWithTitle:@"App List" message:apps delegate:self cancelButtonTitle:@"Ok!" otherButtonTitles:nil];
        [supported show];
        [supported release];
    } else {
        UIAlertView *supported = [[UIAlertView alloc] initWithTitle:@"App List" message:@"Error generating list." delegate:self cancelButtonTitle:@"Ok!" otherButtonTitles:nil];
        [supported show];
        [supported release];
    }
}

アラートを呼び出す前にNSTaskをどのように終了させるかについて何か考えはありますか?ありがとう。

編集:NSNotificationを使用したコード:

-(IBAction) supported {
    stask = [[NSTask alloc] init];
    [stask setLaunchPath:@"/bin/bash"];
    NSString *script;
    script = [[[NSBundle mainBundle] bundlePath] stringByAppendingString:@"/apps.sh"];
    NSArray *sargs = [NSArray arrayWithObjects:script, @"-txt", nil];
    [stask setArguments: sargs];
    [[NSNotificationCenter defaultCenter] addObserver: self
                                             selector: @selector(taskEnded:)
                                                 name: NSTaskDidTerminateNotification
                                               object: nil]; 
    [stask launch];
}

- (void)taskEnded:(NSNotification *)notification {
    if (stask == [[notification object] terminationStatus]) {
        NSString *apps;
        apps = [NSString stringWithContentsOfFile:@"/var/mobile/supported.txt" encoding:NSUTF8StringEncoding error:nil];
        NSFileManager *fm = [NSFileManager defaultManager];
        if ([fm fileExistsAtPath:apps]) {
            UIAlertView *supported = [[UIAlertView alloc] initWithTitle:@"Apps" message:apps delegate:self cancelButtonTitle:@"Ok!" otherButtonTitles:nil];
            [supported show];
            [supported release];
        } else {
            UIAlertView *supported = [[UIAlertView alloc] initWithTitle:@"Apps" message:@"Error generating list." delegate:self cancelButtonTitle:@"Ok!" otherButtonTitles:nil];
            [supported show];
            [supported release];
        }
    } else {
        NSLog(@"Task failed."); 
    }
}
4

3 に答える 3

1

使用しないでくださいwaitUntilExit

問題は、UIをブロックする(またはその1つのボタンをフリーズする)ことなく、タスクの終了後に何かを行う方法です。解決策は、すべての同様の問題と同様に、タスクが終了したときに通知され、その通知に応じてさらに進みます(アラートを表示します)。

この場合の通知は、という名前のNSNotificationNSTaskDidTerminateNotificationです。タスクが終了すると、何らかの理由で、NSTaskオブジェクトはこの通知をデフォルトのNSNotificationCenterに送信します。タスクに終了ステータスを尋ねて、タスクが成功したか、失敗したか、またはクラッシュしたかを判断できます。

参照:通知プログラミングトピック

于 2011-02-28T07:50:34.683 に答える
0

Apple の Moriarity サンプル コードに基づいた AMShellWrapper をご覧ください。

「独自のメソッドを stdout と stderr に接続し、プロセスの終了などについて通知を受けます。」

参照: http://www.cocoadev.com/index.pl?NSTask

于 2011-02-28T11:02:17.847 に答える
0

waitUntilExitメインスレッドでは使用しないでください。これにより、UI がブロックされ、アプリがフリーズします。

タスクの実行が停止したときに投稿される通知NSTaskDidTerminateNotificationにサブスクライブする必要があります。

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(taskDidTerminate:)
                                             name:NSTaskDidTerminateNotification
                                           object:nil];

terminateタスクが正常に完了した場合、またはメッセージの結果として、通知を投稿できることに注意してください。

- (void) taskDidTerminate:(NSNotification *)notification {
    if (YOUR_TASK_SUCCESS_VALUE == [[notification object] terminationStatus]) {
        NSLog(@"Task succeeded.");  
        // Here you can add your checks on the creation on the files and user alerts confirmation
    } else {
        NSLog(@"Task failed."); 
    }
}

通知の購読を解除することを忘れないでください。通知を購読する場所に応じて、deallocメソッドに適切な場所があります。

[[NSNotificationCenter defaultCenter] removeObserver:self];

更新: Mac で文書化されているものは、文書化されていない iOS でも同じように動作すると予想されます。それがうまくいかないのは本当に驚くことではありません。

waitUntilExitバックグラウンド スレッドでタスクを実行し、メソッドを使用しようとしましたか? 運が良ければ、UIAlert を表示するときにメイン スレッドに戻ることを忘れないでください。

于 2011-02-28T08:02:22.267 に答える