Запуск NSTask внутри цикла в Objective-C - PullRequest
0 голосов
/ 06 марта 2012

Я пытаюсь запустить простую команду оболочки, которая довольно быстро запускает и возвращает текст внутри цикла неопределенного размера во время компиляции, генерируемого NSArray. На языках сценариев, таких как Perl, я мог бы сделать что-то вроде этого:

for(i=0;i<=$myinputarraysize;i++){
    $output[i]=`/my/task $inputarray[i]`;
}

Это создаст для меня новый массив из ожидаемого результата моей задачи. В Obj-C это кажется намного сложнее и немного сбивает меня с толку. Прямо сейчас мой цикл выглядит так:

for(int i=0; i<[inputarray count]; i++){
    NSTask *task;
    task = [[NSTask alloc] init];
    [task setLaunchPath:nsdchat];

    NSArray *args;
    args = [NSArray arrayWithObjects:@"/my/task", [inputarray objectAtIndex:i], nil];
    [task setArguments:args];

    NSPipe *pipe;
    pipe = [NSPipe pipe];
    [task setStandardOutput:pipe];

    NSFileHandle *file;
    file = [pipe fileHandleForReading];

    [task launch];

    NSData *data;
    data = [file readDataToEndOfFile];

    NSString *desc;
    desc = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];    
    desc = [string stringByReplacingOccurrencesOfString:@"\n" withString:@""];

    [descriptions insertObject:desc atIndex:i];

    [task release];
    [args release];
    [pipe release];
    [file release];
    [data release]; 
}

Моя цель - заполнить описания (NSMutableArray) выводом из моей задачи (который, как я знаю, всегда является строкой и всегда заканчивается новой строкой, которую я хочу вырезать). Кажется, я что-то упускаю из-за освобождения памяти, так как когда я запускаю это и NSLog вывод, я получаю тот же результат для всего подсчета цикла.

Есть ли какой-нибудь более простой или более простой способ пройтись по таким простым задачам? Я слишком усложняю это для себя?

1 Ответ

0 голосов
/ 06 марта 2012

Прежде всего, нет необходимости выполнять большую часть этой работы внутри цикла.task, pipe и file все выглядит так, как будто они могут обрабатываться вне цикла.Вам также следует рассмотреть возможность использования точечного синтаксиса Objective-C 2.0 и быстрого перечисления, чтобы немного урезать.

Более существенно:

NSArray *args;
args = [NSArray arrayWithObjects:@"/my/task", [inputarray objectAtIndex:i], nil];
[task setArguments:args];

Это говорит о том, что первый аргумент передается в исполняемый файл впуть ndschat равен /my/task.Который, кажется, не соответствует вашему использованию PERL.Вероятно, вы хотите просто:

NSArray *args;
args = [NSArray arrayWithObject:[inputarray objectAtIndex:i]];
[task setArguments:args];

Или, с учетом комментариев стиля:

for(NSString *argument in inputarray)
{
    ...
    task.arguments = [NSArray arrayWithObject:argument];
    ...
}

РЕДАКТИРОВАТЬ: вы также выпускаете много объектов, которые вам не принадлежат,что, как и добавление к вашему коду лишнего кода, является ошибкой управления памятью, которая может привести к сбою.Итак, чтобы сократить все это и исправить эту ошибку:

for(NSString *argument in inputarray)
{
    NSTask *task = [[NSTask alloc] init];  // you now own this
    task.launchPath = nsdchat;

    NSPipe *pipe = [NSPipe pipe];          // you don't own this
    task.standardOutput = pipe;

    NSFileHandle *file = [pipe fileHandleForReading];  // you also don't own this

    task.arguments = [NSArray arrayWithObject:argument];
    [task launch];
    [task waitUntilExit]; // you should wait until the task is done

    NSData *data = [file readDataToEndOfFile];  // this is another thing
                                                // you don't own. Note also that
                                                // readDataToEndOfFile advances
                                                // the current read pointer, so
                                                // it should be fine to do this
                                                // successively 

    NSString *desc;
    desc = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] 
                                                                   autorelease];    
                                                // you don't own this because
                                                // of the autorelease; you
                                                // don't want to own it since
                                                // the next line will throw
                                                // it away


    desc = [string stringByReplacingOccurrencesOfString:@"\n" withString:@""];
                                                // you don't own this

    [descriptions addObject:desc];
    [task release];
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...