1

2 秒ごとにスクリプトを実行し、出力をメニュー バー項目に配置する非常に単純なプログラムがあります。ただし、約 90 分後にメニュー バー項目の更新が停止します。誰でも理由がわかりますか?

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    [_window setIsVisible:NO];
    ProcessSerialNumber psn = { 0, kCurrentProcess };
    TransformProcessType(&psn, kProcessTransformToUIElementApplication);
    //the above code stops the dock icon from appearing (and also stops the application from appearing in the alt tab menu

    statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];
    [statusItem setHighlightMode:YES];
    [statusItem setTitle:@"0%"]; 
    [statusItem setEnabled:YES];
    [statusItem setToolTip:@"Script output"];

    //[statusItem setAction:@selector(updateIPAddress:)];
    [statusItem setTarget:self];

    //NSString *output = [self unixSinglePathCommandWithReturn:@"/usr/bin/osascript \"/Users/Velox/Projects/Geektool Scripts/WorkDay.scpt\""];

    [NSThread detachNewThreadSelector:@selector(calcPercent) toTarget:[self class] withObject:nil];
}

+(void)calcPercent{
    while(true){
        NSString *output = [self unixSinglePathCommandWithReturn:@"/usr/bin/osascript \"/Users/Velox/Projects/Geektool Scripts/WorkDay.scpt\""];
        [statusItem setTitle:output];
        [statusItem setEnabled:YES];
        [NSThread sleepForTimeInterval:2];
    }
}

+ (NSString *)unixSinglePathCommandWithReturn:(NSString *) command {

    NSPipe *newPipe = [NSPipe pipe];
    NSFileHandle *readHandle = [newPipe fileHandleForReading];
    NSData *inData = nil;
    NSString* returnValue = nil;

    NSTask *unixTask = [[NSTask alloc] init];

    unixTask = [[NSTask alloc] init];
    [unixTask setStandardOutput:newPipe];
    [unixTask setLaunchPath:@"/bin/csh"];
    [unixTask setArguments:[NSArray arrayWithObjects:@"-c", command , nil]]; 
    [unixTask launch];
    [unixTask waitUntilExit];
    //int status = [unixTask terminationStatus];

    while ((inData = [readHandle availableData]) && [inData length]) {

        returnValue= [[NSString alloc] initWithData:inData encoding:[NSString defaultCStringEncoding]];

        returnValue = [returnValue substringToIndex:[returnValue length]-1];

    }

    return returnValue;

}

ARCを使用しています。

ありがとう。

4

1 に答える 1

0

ARCを使用しているからといって(全体として素晴らしいことです)、メモリの使用とパフォーマンスについて考えるのをやめる必要があるわけではありません。

" calcPercent"メソッドでは、""を繰り返し呼び出していますunixSinglePathCommandWithReturn:。returnValueが割り当てられ、設定されて " while"ループから抜け出したら、 ""を実行する必要がありますunixTask = nil;。これにより、ARCはunixタスクオブジェクトを適切に解放します。

もう1つ、2秒ごとに呼び出しています。ポーリングは非常に無駄なので、自分がやろうとしていることを実行するためのより良い方法を考え出すようにしてください。たとえば、2秒ごとではなく(その関数への他の複数の呼び出しがスタックしたりハングしたりする可能性があります)、前回の ""の呼び出しが終了してから2秒後unixSinglePathCommandWithReturnに実行するようにスケジュールしませんか?

ところで、あなたは次々に " unixTask"("への2つの別々の呼び出しで)を二重に割り当てています。[NSTask alloc] init]これが非ARCコードの場合、それは大きなメモリリークになります。今のところ、見た目が悪いだけです。

于 2012-06-22T12:12:34.807 に答える