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