1

我正在将一些执行 AppleScripts 的代码从 NSAppleScript 迁移到 NSUserAppleScriptTask,以便我可以对我的应用程序进行沙箱处理。我遇到的问题可以最好地证明如下:

AppleScript“test.scpt”很简单

on run
  display dialog "Hello World" buttons {"OK"} default button "OK"
end run

如果我使用如下 NSAppleScript 连续执行 10 次,则脚本会执行 10 次,每次执行都等待上一次执行完成。

NSURL *script = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"test" ofType:@"scpt"]];

for (int i=0; i<10; i++) {

    NSDictionary *error = nil;
    NSAppleScript *task = [[NSAppleScript alloc] initWithContentsOfURL:script error:nil];
    [task executeAndReturnError:&error];
    if (error!=nil) {
        NSLog(@"AppleScript error: %@", error);
    }
    [task release];
}

但是使用 NSUserAppleScriptTask 似乎任务是同时执行的。并发执行是一个“问题”,因为如果前一个脚本打开了一个对话框,下一个要执行的脚本就会出错。这可以证明如下:

NSURL *script = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"test" ofType:@"scpt"]];


for (int i=0; i<10; i++) {

    NSError *error;
    NSUserAppleScriptTask *task = [[NSUserAppleScriptTask alloc] initWithURL:script error:&error];
    [task executeWithCompletionHandler:^(NSError *error) {
        if (error){
            NSLog(@"Script execution failed with error: %@", [error localizedDescription]);
        }
    }];

   [task release];

}

这会为 10 次执行中的 9 次生成以下错误:

execution error: "Hello World" doesn’t understand the «event sysodlog» message. (-1708)

我认为正确的解决方案是使用 gcd 或 NSOperationQueue 对每个操作进行排队,但我没有设法构建一个队列,等待 NSUserAppleScriptTask 的完成块在它开始下一个任务之前执行。

任何人都可以提出一个解决方案,它会给我与 NSAppleScript 方法给我的行为相同的行为吗?

4

3 回答 3

2

您可以从调度队列(或操作队列)运行脚本并使用NSConditionLock等待每个脚本完成。

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    NSConditionLock *lock = [[NSConditionLock alloc] initWithCondition:0];

    NSURL *script = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"test" ofType:@"scpt"]];
    for (int i=0; i<10; i++) {
        NSError *error;
        NSUserAppleScriptTask *task = [[NSUserAppleScriptTask alloc] initWithURL:script error:&error];
        [task executeWithCompletionHandler:^(NSError *error) {
            if (error){
                NSLog(@"Script execution failed with error: %@", [error localizedDescription]);
            }
            [lock lock];
            [lock unlockWithCondition:1];
        }];
        [task release];

        //This will wait until the completion handler of the script task has run:
        [lock lockWhenCondition:1];
        [lock unlockWithCondition:0];
    }
    [lock release];
});
于 2013-01-12T14:22:16.280 回答
1

(受上面 omz 评论的启发,我写这个作为答案。)

您可以使用任务的完成处理程序开始执行下一个任务。

于 2013-01-12T14:44:17.027 回答
0

你是如何通过沙盒的?无论我尝试什么,我都会得到类似的东西:

Script execution error: The file “create.scpt” couldn’t be opened because you don’t have permission to view it.

关闭沙盒或手动执行脚本时,一切正常

权利:

com.apple.security.temporary-exception.apple-events
com.apple.systemevents
com.apple.applescript

泰。

编辑:似乎如果我将脚本放入 ~/Library/Application Scripts/com.myapp/ 并执行该脚本一切正常

于 2013-02-11T13:45:18.407 回答