所以我有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.");
}
}
答案 0 :(得分:1)
请勿使用waitUntilExit
。
问题是在任务完成后如何在不阻止UI(或冻结那个按钮)的情况下执行某些操作。对于所有类似问题,解决方案是在任务完成时被通知,并进一步继续(显示警报)以响应该通知。
在这种情况下,通知是名为NSTaskDidTerminateNotification
的NSNotification。当任务退出时,无论出于何种原因,NSTask对象都会在默认的NSNotificationCenter上发布此通知。您可以询问任务的终止状态,以确定它是成功,失败还是崩溃。
答案 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,获得有关进程终止的通知等等。”