2013-01-12 48 views
1

我正在將一些執行AppleScripts的代碼從NSAppleScript遷移到NSUserAppleScriptTask,以便我可以對我的應用程序進行沙盒處理。執行腳本如何排隊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]; 

} 

這生成9以下錯誤出10所執行的:

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

我認爲正確的解決方案將是隊列使用GCD或NSOperationQueue每個操作但我沒有設法構建一個隊列,等待NSUserAppleScriptTask的完成塊在其開始下一個任務之前執行。

任何人都可以提出一個解決方案,會給我與NSAppleScript方法給我一樣的行爲嗎?

+1

您可以使用任務的完成處理程序開始執行下一個任務。 –

+0

這可能比我的更好(更直接)的解決方案。 – omz

回答

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

謝謝!雖然Martin的解決方案對我的簡化示例也是正確的,但實際上我並不處於循環中,並且不知道下一個腳本何時會被執行,所以OMZ的答案對我來說是完美的。再次感謝。 – davidb

1

(由OMZ的評論上面的啓發我寫這篇文章作爲一個答案。)

您可以使用任務的完成處理程序來啓動下一個任務的執行。

+0

感謝您的回答 - 對於所問的問題的確是正確的,但似乎我對OMZ的解決方案發表了評論。再次感謝 - 大衛 – davidb

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 

TY。

編輯: 看來,如果我把腳本到〜/庫/應用程序腳本/ com.myapp /和執行該腳本一切工作正常

+0

同樣的事情發生在我身上。我的目標是10.11。當.scpt文件駐留在應用程序包內時,NSUserAppleScriptTask會引發權限錯誤。 只有當我把文件放到〜/ Library/Application Scripts/com.myapp文件夾時,纔有效,並且在任務運行之前通過文件瀏覽器進行選擇。手動構建的NSURL似乎從來不適用於NSUserAppleScriptTask。 ; / –