2012-03-06 17 views
0

NSArrayによって生成されたコンパイル時に不確定なサイズのループ内でテキストが実行され、かなり速く返される単純なシェルコマンドを実行しようとしています。 perlのようなスクリプト言語では、私は次のようなことをすることができます:Objective-Cでループ内でNSTaskを実行しています

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にすると、ループのカウント全体で同じ結果が得られるので、メモリの解放に関する何かが不足しているようです。

このような単純なタスクをループする方法はありますか。私はそれを自分のために過度に複製していますか?

+0

私は混乱しています - ログには何が印刷されていますか?これはうまくいくはずです。 –

答えて

0

まず、ループ内でその作業のほとんどを行う必要はありません。 taskpipeおよび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]; 
    ... 
} 

EDIT:あなたも、あなたが所有していない多数のオブジェクトを解放している、などをコードに重大さを追加すると、クラッシュする可能性のあるメモリ管理エラーが発生します。だから、全体をカットして、その欠陥を修正する:

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]; 
} 
+0

これはまだまだ新しいので、疑問の言い訳を言い訳にしますが、NSPipe *が所有しているので、NSPipe *パイプを所有していませんか?オブジェクトの継承はまだ少し混乱しています。私はループの最上部でそれらを元に戻すことができるようにしようとしているオブジェクトをリリースしていましたが、なぜこれが間違っている(オーナーシップ)のか私には明らかです。 – szumlins

+0

Objective-Cは、形式的な言語文法の代わりに多くの慣習を持ち、コンストラクタもその一つです。ルールは、オブジェクトを保持する手段が、 'new'、 'alloc'、 'retain'または 'create'(NARCはニーモニック)という単語を持たない場合は、所有していない参照。あなたが参照を所有していない場合は、それを '解放 'する必要はありません。しかし、AppleはXcodeの最近のバージョンにARC(自動参照カウント)コンパイラを追加したので、あなたがしたくない場合は、これ以上何も考えなくて済むようになりました。 – Tommy

+0

おっと!それはコピーであり、作成ではありません。あなたはCore Foundationのものを作成します。これはある意味では「所有する参照」を意味しますが、Cのメモリ管理(つまり、参照カウントなし)はまったく別のトピックです。 – Tommy

関連する問題