[英]Running NSTask inside a loop in Objective-C
I am trying to run a simple shell command that runs and returns text rather quickly inside of a loop of indeterminate size at compile time that is generated by an NSArray. 我试图运行一个简单的shell命令,该命令在NSArray生成的编译时在不确定大小的循环内相当快地运行并返回文本。 In scripting languages like perl, I would be able to do something like this:
在像perl这样的脚本语言中,我将能够执行以下操作:
for(i=0;i<=$myinputarraysize;i++){
$output[i]=`/my/task $inputarray[i]`;
}
This would build a new array for me from the expected output of my task. 这将从任务的预期输出为我构建一个新数组。 In Obj-C this seems to be much more difficult and a bit confusing to me.
在Obj-C中,这似乎要困难得多,并且让我感到困惑。 Right now my loop looks like this:
现在我的循环看起来像这样:
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];
}
My goal is to fill descriptions (an NSMutableArray) with the output from my task (which I know is always a string and always ends in a newline that I want to strip out). 我的目标是用任务的输出(我知道总是一个字符串,并且总是以我要删除的换行符结尾)填充描述(一个NSMutableArray)。 It seems I'm missing something about memory releasing as when I run this and NSLog the output, I get the same result for the entire count of the loop.
似乎我缺少有关内存释放的信息,因为当我运行此命令并输出NSLog时,整个循环的计数结果相同。
Is there any easier or more way to loop through simple tasks like this? 有没有更简单或更简单的方法循环遍历这样的简单任务? Am I overcomplicating it for myself?
我是否为自己过于复杂?
First of all, there's no need to do most of that work inside the loop. 首先,不需要在循环内完成大部分工作。
task
, pipe
and file
all look like they could be handled outside the loop. task
, pipe
和file
看起来都可以在循环外处理。 You should also consider using Objective-C 2.0 dot syntax and fast enumeration to cut things down a little. 您还应该考虑使用Objective-C 2.0点语法和快速枚举来减少一些麻烦。
More significantly: 更重要的是:
NSArray *args;
args = [NSArray arrayWithObjects:@"/my/task", [inputarray objectAtIndex:i], nil];
[task setArguments:args];
This says that the first argument passed to the executable at path ndschat
is /my/task
. 这表示传递到路径
ndschat
的可执行文件的第一个参数是/my/task
。 Which doesn't seem to match your PERL usage. 这似乎与您的PERL使用情况不符。 Probably you want just:
可能您只想:
NSArray *args;
args = [NSArray arrayWithObject:[inputarray objectAtIndex:i]];
[task setArguments:args];
Or, with the style comments taken into account: 或者,考虑到样式注释:
for(NSString *argument in inputarray)
{
...
task.arguments = [NSArray arrayWithObject:argument];
...
}
EDIT: you're also releasing a lot of objects you don't own, which as well as adding heft to your code is a memory management error possibly leading to a crash. 编辑:您还释放了许多您不拥有的对象,以及在代码中增加大量内容是可能导致崩溃的内存管理错误。 So, to cut the whole thing down and correct that fault:
因此,要减少整个故障并纠正该故障:
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];
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.