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

发布于 2024-10-19 09:34:03 字数 2812 浏览 1 评论 0原文

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

So I've got NSTask to run a script which generates a list of something, into a txt, which I read from. But if I use my current code (below), the alert pops up before the NSTask is finished, thus resulting in a blank alert. I've tried waitUntilExit but that makes the button that invokes this action freeze, but the UI doesn't lock up itself.

- (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];
    }
}

Any idea how I'd have the NSTask finish before invoking the alert? Thanks.

Edit: Code with 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."); 
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

感性不性感 2024-10-26 09:34:03

不要使用waitUntilExit

问题是如何在任务完成后执行某些操作而不阻塞 UI(或冻结该按钮)。对于所有类似的问题,解决方案是在任务完成时收到通知,并进一步处理(显示警报)以响应该通知。

在本例中,通知是一个名为 NSTaskDidTerminateNotification 的 NSNotification。当任务由于任何原因退出时,NSTask 对象会在默认的 NSNotificationCenter 上发布此通知。您可以询问任务的终止状态是什么,以确定它是成功、失败还是崩溃。

另请参阅:通知编程主题

Don't use waitUntilExit.

The problem is how to do something after the task finishes without blocking the UI (or freezing that one button). The solution, as for all similar problems, is to be notified when the task finishes, and proceed further (show the alert) in response to that notification.

The notification, in this case, is an NSNotification named NSTaskDidTerminateNotification. When the task exits, for any reason, the NSTask object will post this notification on the default NSNotificationCenter. You can ask the task what its termination status was to determine whether it succeeded, failed, or crashed.

See also: Notification Programming Topics.

还在原地等你 2024-10-26 09:34:03

看一下 AMShellWrapper,它基于 Apple 的 Moriarity 示例代码。

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

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

Have a look at AMShellWrapper which is based on Apple's Moriarity sample code.

"Connect your own methods to stdout and stderr, get notified on process termination and more."

See: http://www.cocoadev.com/index.pl?NSTask

冧九 2024-10-26 09:34:03

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

Don't use waitUntilExit on your main thread. That will block your UI, and freeze your app.

You need to subscribe to the notification NSTaskDidTerminateNotification, which is posted when the task has stopped execution:

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

Note that the notification can be posted if the task completed normally, or as the result of a terminate message:

- (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."); 
    }
}

Don't forget to unsubscribe to the notification ; depending on where you subscribe to the notification, a good place would be in your dealloc method:

[[NSNotificationCenter defaultCenter] removeObserver:self];

Update: You expect something that is documented on Mac to work the same on iOS, where it is not documented. Not really surprised it doesn't work.

Have you tried to execute the task - and use the waitUntilExit method - in a background thread?
If you are lucky and it works, don't forget to switch back to the main thread when showing your UIAlert.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文