Ale*_*lex 7 cocoa objective-c nstask appstore-sandbox
我一直试图用最近的NSUserScriptTask类及其子类来做(看到这个和这个),到目前为止我已经解决了一些问题,但还有一些问题仍有待解决.从文档中可以看出,NSUserScriptTask不允许取消任务.因此,我决定创建一个简单的可执行文件,将脚本的路径作为参数并运行脚本.这样,我可以使用NSTask从我的主应用程序启动帮助程序,并[task terminate]在必要时调用.但是,我要求:
主应用程序的代码很简单:只需使用正确的信息启动NSTask即可.这就是我现在所拥有的(为了简单起见,我忽略了安全范围的书签之类的代码,这些代码都没有问题.但是不要忘记这是运行沙盒的):
// Create task
task = [NSTask new];
[task setLaunchPath: [[NSBundle mainBundle] pathForResource: @"ScriptHelper" ofType: @""]];
[task setArguments: [NSArray arrayWithObjects: scriptPath, nil]];
// Create error pipe
NSPipe* errorPipe = [NSPipe new];
[task setStandardError: errorPipe];
// Create output pipe
NSPipe* outputPipe = [NSPipe new];
[task setStandardOutput: outputPipe];
// Set termination handler
[task setTerminationHandler: ^(NSTask* task){        
    // Save output
    NSFileHandle* outFile = [outputPipe fileHandleForReading];
    NSString* output = [[NSString alloc] initWithData: [outFile readDataToEndOfFile] encoding: NSUTF8StringEncoding];
    if ([output length]) {
        [output writeToFile: outputPath atomically: NO encoding: NSUTF8StringEncoding error: nil];
    }
    // Log errors
    NSFileHandle* errFile = [errorPipe fileHandleForReading];
    NSString* error = [[NSString alloc] initWithData: [errFile readDataToEndOfFile] encoding: NSUTF8StringEncoding];
    if ([error length]) {
        [error writeToFile: errorPath atomically: NO encoding: NSUTF8StringEncoding error: nil];
    }
    // Do some other stuff after the script finished running <-- IMPORTANT!
}];
// Start task
[task launch];
请记住,我需要终止处理程序仅在以下情况下运行:(a)任务被取消(b)任务因脚本完成运行而自行终止.
现在,在辅助方面,事情开始变得毛茸茸,至少对我而言.让我们想象一下,为了简单起见,脚本是一个AppleScript文件(所以我使用NSUserAppleScriptTask子类 - 在现实世界中,我必须适应这三种类型的任务).这是我到目前为止所得到的:
int main(int argc, const char * argv[])
{
    @autoreleasepool {
        NSString* filePath = [NSString stringWithUTF8String: argv[1]];
        __block BOOL done = NO;
        NSError* error;
        NSUserAppleScriptTask* task = [[NSUserAppleScriptTask alloc] initWithURL: [NSURL fileURLWithPath: filePath] error: &error];
        NSLog(@"Task: %@", task); // Prints: "Task: <NSUserAppleScriptTask: 0x1043001f0>" Everything OK
        if (error) {
            NSLog(@"Error creating task: %@", error); // This is not printed
            return 0;
        }
        NSLog(@"Starting task");
        [task executeWithAppleEvent: nil completionHandler: ^(NSAppleEventDescriptor *result, NSError *error) {
            NSLog(@"Finished task");
            if (error) {
                NSLog(@"Error running task: %@", error);
            }
            done = YES;
        }];
        // Wait until (done == YES). How??
    }
    return 0;
}
现在,我有三个问题(我想问这个SO条目的问题).首先,"完成的任务"永远不会被打印(块永远不会被调用)因为任务从未开始执行.相反,我在我的控制台上得到了这个:
MessageTracer: msgtracer_vlog_with_keys:377: odd number of keys (domain: com.apple.automation.nsuserscripttask_run, last key: com.apple.message.signature)
我尝试从主应用程序运行完全相同的代码,它完成没有大惊小怪(但从主应用程序,我失去了取消脚本的能力).
其次,我只想在return 0;调用完成处理程序后到达main()的末尾.但我不知道该怎么做.
三,每当帮助器出现错误或输出时,我想将该错误/输出发送回应用程序,该应用程序将通过errorPipe/outputPipe接收它们.类似fprintf(stderr/stdout, "string")的伎俩,但我不确定这是否是正确的方法.
因此,简而言之,对第一和第二个问题的任何帮助都表示赞赏.第三个我只是想确保我应该怎么做.
谢谢
问题1:子任务没有运行,因为它的父任务立即退出。(有关“奇数个键”的日志消息是 中的一个错误NSUserScriptTask,发生的原因是您的助手没有包标识符,但在其他方面是无害的并且与您的问题无关。)它立即退出,因为它不等待完成块着火,这让我们……
问题2:如何等待异步完成块?这已经在其他地方得到了回答,包括等待多个网络请求全部执行 - 包括它们的完成块,但回顾一下,使用调度组,如下所示:
dispatch_group_t g = dispatch_group_create();
dispatch_group_enter(g);
[task executeWithAppleEvent:nil completionHandler:^(NSAppleEventDescriptor *result, NSError *e) {
    ...
    dispatch_group_leave(g);
}];
dispatch_group_wait(g, DISPATCH_TIME_FOREVER);
dispatch_release(g);
同样的模式适用于任何具有您想要等待的完成块的调用。如果您希望在组完成时收到另一个通知而不是等待它,请使用dispatch_group_notify而不是dispatch_group_wait。
| 归档时间: | 
 | 
| 查看次数: | 1020 次 | 
| 最近记录: |