NSTask waitUntilExit висит приложение на взломанной iOS - PullRequest
2 голосов
/ 28 февраля 2011

Итак, у меня есть NSTask для запуска скрипта, который генерирует список чего-либо, в текстовый файл, из которого я читаю.Но если я использую свой текущий код (ниже), предупреждение появляется до завершения NSTask, что приводит к пустому предупреждению.Я пробовал waitUntilExit, но это заставляет кнопку, которая вызывает это действие, зависать, но пользовательский интерфейс не блокируется сам по себе.оповещать?Спасибо.

Редактировать: Код с 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."); 
    }
}

Ответы [ 3 ]

1 голос
/ 28 февраля 2011

Не используйте waitUntilExit.

Проблема в том, как сделать что-то после завершения задачи, не блокируя пользовательский интерфейс (или не останавливая эту одну кнопку). Решение, как и для всех аналогичных проблем, состоит в том, чтобы получать уведомление о завершении задачи и продолжать (показывать предупреждение) в ответ на это уведомление.

Уведомление, в данном случае, является NSNotification с именем NSTaskDidTerminateNotification. Когда по какой-либо причине задача завершается, объект NSTask отправит это уведомление в NSNotificationCenter по умолчанию. Вы можете задать задаче, каково ее состояние завершения, чтобы определить, успешно она выполнена, не выполнена или произошла ошибка.

См. Также: Темы программирования уведомлений .

0 голосов
/ 28 февраля 2011

Взгляните на AMShellWrapper, основанный на примере кода Apple Moriarity.

"Подключите свои собственные методы к stdout и stderr, получите уведомление о завершении процесса и т. Д."

См.http://www.cocoadev.com/index.pl?NSTask

0 голосов
/ 28 февраля 2011

Не используйте waitUntilExit в вашем основном потоке. Это заблокирует ваш пользовательский интерфейс и заблокирует ваше приложение.

Вам необходимо подписаться на уведомление 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.

...