从Cocoa应用程序(通过NSTask)运行xcodebuild两次无声地失败

时间:2012-02-27 20:52:18

标签: objective-c xcode cocoa xcodebuild nstask

我有一个Cocoa应用程序可以执行许多操作,但在其中,使用“xcodebuild”来清理并重新构建XCode中的iOS项目。 Cocoa应用程序是使用XCode 4.1开发的,仅在OS X 10.7上运行(因为NSTask终止处理程序)。我几个月没碰过它,在我升级到XCode 4.2之后,我发现只有运行xcodebuild的第一个NSTask实际上做了什么。后续调用什么都不做。

一些细节:

  • 正在构建的iOS项目位于Cocoa应用程序的资源包中。所以基本上,Cocoa应用程序是iOS项目的包装器。想象一下带有一个大红色按钮的GUI,上面写着:“构建一个iOS应用程序!”
  • 此代码在XCode 4.1中运行良好。执行任务1,然后在任务1的终止处理程序中,调用任务2,并运行得很好。问题是任务2根本不再运行。
  • 我已经升级到xcode 4.3,这要求我也安装独立的Xcode命令行工具。但是代码仍然无法正常工作。
  • 我可以在终端中同时运行“xcodebuild clean”和“xcodebuild”命令。

以下是违规代码的(转述)版本。

#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

所以只需重新迭代:任务1(干净)工作正常。任务2(构建)似乎甚至没有启动。仅在升级到XCode 4.2后才会出现此行为。我一定做错了什么,但是什么?

2 个答案:

答案 0 :(得分:1)

似乎我遇到了Xcode中的一个错误,类似于: NSTask NSPipe - objective c command line help

基本上,如果NSTask已经启动一次,Xcode将保留NSTask的输出。

解决方案是切换任务的标准输入:

[task setStandardInput:[NSPipe pipe]];

只要我把它放到runTaskOne方法中,一切都开始运行得很好。

答案 1 :(得分:0)

如果您的项目使用ARC(自动引用计数),NSTask实例将在runTaskOne方法结束时自动释放。因此,永远不会调用完成处理程序,因为应该观察该进程的对象不再存在。

您需要通过将任务存储在实例变量中来保留对该任务的引用。