Двойной запуск xcodebuild из приложения Cocoa (через NSTask) завершается неудачно - PullRequest
1 голос
/ 28 февраля 2012

У меня есть приложение Какао, которое делает несколько вещей, но среди них использует 'xcodebuild', чтобы очистить и пересобрать проект iOS в XCode. Приложение Cocoa было разработано с использованием XCode 4.1 и работает только на OS X 10.7 (из-за обработчиков завершения NSTask). Я не трогал его в течение нескольких месяцев, и после того, как я обновился до XCode 4.2, я обнаружил, что только первый NSTask, который запускал xcodebuild, на самом деле что-то делал. Последующие звонки ничего не делают.

Некоторые детали:

  • Строящийся проект iOS находится в пакете ресурсов приложения Cocoa. В общем, приложение Cocoa - это оболочка для проекта iOS. Представьте себе графический интерфейс с большой красной кнопкой, которая говорит: «Построй мне приложение для 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 ]

1 голос
/ 28 февраля 2012

Кажется, что я столкнулся с ошибкой в ​​Xcode, что-то похожее на это: NSTask NSPipe - целевая справка по командной строке

По сути, XCode будет удерживать вывод NSTask, если NSTask уже был запущен один раз.

Решением было переключить стандартный ввод Задачи таким образом:

[task setStandardInput:[NSPipe pipe]];

Как только я поместил это в метод runTaskOne, все стало работать хорошо.

0 голосов
/ 28 февраля 2012

Если ваш проект использует ARC (автоматический подсчет ссылок), экземпляр NSTask автоматически освобождается в конце метода runTaskOne. Таким образом, обработчик завершения никогда не вызывается, потому что объект, который должен наблюдать за процессом, больше не существует.

Необходимо сохранить ссылку на задачу, сохранив ее в переменной экземпляра.

...