NSTask waitUntilExit在越狱iOS上挂起应用程序

时间:2011-02-28 07:06:30

标签: iphone objective-c cocoa jailbreak nstask

所以我有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."); 
    }
}

3 个答案:

答案 0 :(得分:1)

请勿使用waitUntilExit

问题是在任务完成后如何在不阻止UI(或冻结那个按钮)的情况下执行某些操作。对于所有类似问题,解决方案是在任务完成时被通知,并进一步继续(显示警报)以响应该通知。

在这种情况下,通知是名为NSTaskDidTerminateNotification的NSNotification。当任务退出时,无论出于何种原因,NSTask对象都会在默认的NSNotificationCenter上发布此通知。您可以询问任务的终止状态,以确定它是成功,失败还是崩溃。

另请参阅:Notification Programming Topics

答案 1 :(得分:0)

不要在主线程上使用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时切换回主线程。

答案 2 :(得分:0)

查看基于Apple的Moriarity示例代码的AMShellWrapper。

“将您自己的方法连接到stdout和stderr,获得有关进程终止的通知等等。”

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