I have a Cocoa app that does a number of things, but among them, uses ' xcodebuild
' to clean and re-build a iOS project in XCode. The Cocoa app was developed using XCode 4.1, and runs only on OS X 10.7 (because of the NSTask termination handlers). I hadn't touched it for a few months, and after I had upgraded to XCode 4.2 I found that only the first NSTask that ran xcodebuild actually did anything. Subsequent calls do nothing.
Some details:
xcodebuild clean
' and ' xcodebuild
' commands in Terminal with no problems. Below is a (paraphrased) version of the offending code.
#import "AppDelegate.h"
@implementation AppDelegate
@synthesize window = _window;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
[self runTaskOne];
}
// Clean the iOS Project
- (void) runTaskOne
{
NSTask *task = [[NSTask alloc] init];
[task setCurrentDirectoryPath:@".../myproject/DerivedData/myproject/Build/Products/Debug/myproject.app/Contents/Resources/iOSProjectFolder"];
[task setLaunchPath:@"/usr/bin/xcodebuild"];
[task setArguments:[NSArray arrayWithObjects:@"clean", nil]];
[task setTerminationHandler:^(NSTask *task)
{
[self runTaskTwo];
}];
[task launch];
}
// Build the same iOS project that was just cleaned
- (void) runTaskTwo;
{
NSTask *task = [[NSTask alloc] init];
[task setCurrentDirectoryPath:@".../myproject/DerivedData/myproject/Build/Products/Debug/myproject.app/Contents/Resources/iOSProjectFolder"];
[task setLaunchPath:@"/usr/bin/xcodebuild"];
[task launch];
}
@end
So just to re-iterate: Task 1 (the clean) works fine. Task 2 (the build) doesn't even seem launch. This behaviour is only observed after upgrading to XCode 4.2. I must be doing something wrong, but what?
It seems as though I ran into a bug in Xcode, something similar to this: NSTask NSPipe - objective c command line help
Basically, Xcode will hold on to the output of the NSTask if NSTask has already been launched once.
The solution was to switch the Task's standard input thusly:
[task setStandardInput:[NSPipe pipe]];
As soon as I put that into the runTaskOne method, everything started working nicely.
If your project uses ARC (Automatic Reference Counting), the NSTask
instance is automatically released at the end of the runTaskOne
method. So the completion handler is never invoked because the object that is supposed to observe the process no longer exists.
You need to keep a reference to the task by storing it in an instance variable.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.