【问题标题】:Running xcodebuild twice from a Cocoa app (via NSTask) silently fails从 Cocoa 应用程序(通过 NSTask)静默运行 xcodebuild 两次失败
【发布时间】:2012-02-27 20:52:18
【问题描述】:

我有一个 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 后才会观察到此行为。我一定是做错了什么,但是什么?

【问题讨论】:

  • 确实如此。实际上,我刚刚注意到任务 1 的终止处理程序从未运行。 ... Aaand 经过一番搜索,我找到了答案。现在就写吧。

标签: objective-c xcode cocoa xcodebuild nstask


【解决方案1】:

好像我在 Xcode 中遇到了一个错误,类似于以下内容: NSTask NSPipe - objective c command line help

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

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

[task setStandardInput:[NSPipe pipe]];

我将它放入 runTaskOne 方法后,一切都开始运行良好。

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 感谢尼古拉斯的回复。我发现通过将管道作为标准输入添加到任务中,例如:[task setStandardInput:[NSPipe pipe]]; 可以解决问题。终止处理程序已运行,一切正常。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-04
    • 2012-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多