最近写了一个小软件 WebDrop ,尝试了下上架,关于如何在沙盒内调用 Apple Script 写一点相关的内容。
先看一个 Code Snippet
NSAppleScript *script= [[NSAppleScript alloc] initWithSource:@"tell application \"Safari\" to return URL of front document as string"];
NSDictionary *scriptError = nil;
NSAppleEventDescriptor *descriptor = [script executeAndReturnError:&scriptError];
if(scriptError)
{
NSLog(@"Error: %@",scriptError);
} else
{
NSAppleEventDescriptor *unicode = [descriptor coerceToDescriptorType:typeUnicodeText];
NSData *data = [unicode data];
NSString *result = [[NSString alloc] initWithCharacters:(unichar*)[data bytes] length:[data length] / sizeof(unichar)];
}
这段代码会返回当前 Safari 最前 Tab 的网页地址,但是只限于没有开启 App Sandbox 的情况 —— 如果开启了 Sandbox,就会出现以下错误:
2016-06-24 10:41:10.022 WebDrop[81536:1628248] Error: {
NSAppleScriptErrorAppName = Safari;
NSAppleScriptErrorBriefMessage = "\U5e94\U7528\U7a0b\U5e8f\U6ca1\U6709\U8fd0\U884c\U3002";
NSAppleScriptErrorMessage = "\U201cSafari\U201d\U9047\U5230\U4e00\U4e2a\U9519\U8bef\Uff1a\U5e94\U7528\U7a0b\U5e8f\U6ca1\U6709\U8fd0\U884c\U3002";
NSAppleScriptErrorNumber = "-600";
NSAppleScriptErrorRange = "NSRange: {61, 6}";
}
其中的 Unicode 为:“应用程序没有运行。”,这是因为沙盒阻止 Apple Script 访问 Safari 了,这个时候有两个解决办法。
第一个见 http://objccn.io/issue-14-2/,首先这个方法好像是不能上 MAS 的,因为其中采用的方法是安装 .scpt 到用户文件夹下,我用这个方法上架时审核人员给出以下的理由:
Performance - 2.4.5
Your app installs an AppleScript in shared locations.
Specifically the app installs an AppleScript into the Application Scripts folder.
我也不知道为什么审核人员不给用这种方法,而必须要求 Apple Script 储存在 Container 内 (参见 stackoverflow),不过既然如此,就只能用另一个方法了...
第二个就是加 Entitlement key,有两个 key 可以添加,一个是 com.apple.security.scripting-targets
(Reference),一个是 com.apple.security.temporary-exception.apple-events
(Reference),其中前者更推荐,使用起来是这样的:
<key>com.apple.security.scripting-targets</key>
<dict>
<key>com.apple.mail</key>
<array>
<string>com.apple.mail.compose</string>
</array>
</dict>
后者的话简单一些,不用配置特定的动作,只要写 bundle id 就可以(注意要全小写)
<key>com.apple.security.temporary-exception.apple-events</key>
<array>
<string>com.google.chrome.canary</string>
<string>com.google.chrome</string>
<string>com.apple.safari</string>
<string>com.vivaldi.vivaldi</string>
<string>org.webkit.nightly.webKit</string>
</array>