使用带有Chrome的Scripting Bridge强制解包错误

时间:2017-03-05 20:40:55

标签: swift applescript applescript-objc

我正在尝试使用Apple的Scripting Bridge与Google Chrome进行互动。我已经开始使用https://stackoverflow.com/a/24147285

中的代码了

我使用.hsdef命令创建了sdp文件。

我已经包含了该文件,并在桥接标题中创建了桥接标题和导入的chrome头文件。但问题是在Swift中使用标头。代码很旧,Swift发生了很大的变化。

My Swift文件:

import Cocoa
import ScriptingBridge


var chromeObject = SBApplication.init(bundleIdentifier: "com.google.Chrome")! as AnyObject

print(chromeObject.closeable)

我收到错误

  

致命错误:在解包可选值时意外发现nil

我做错了什么?

2 个答案:

答案 0 :(得分:2)

SBApplication返回Application对象。您可以在interface文件中看到不同的.h

@interface ChromeApplication : SBApplication
@interface ChromeWindow : SBObject <ChromeGenericMethods>
@interface ChromeApplication (ChromiumSuite)
@interface ChromeTab : SBObject <ChromeGenericMethods>
@interface ChromeBookmarkFolder : SBObject <ChromeGenericMethods>
@interface ChromeBookmarkItem : SBObject <ChromeGenericMethods>

因此,SBApplication会向您返回ChromeApplication。您可以调用ChromeApplication中定义的任何属性。亲自尝试一下。你不会得到任何错误。

问题是您正在调用closeable ChromeWindow的一部分。

来自Apple Documentation

  

AppleScript和对象

     

AppleScript是一种面向对象的语言。当你写,编译,   并执行脚本,您使用的所有内容都是一个对象。一个东西   是类定义的实例化,可以包括   属性和动作。 AppleScript定义对象的类   最常用的工作,从顶级脚本开始   对象,这是您正在使用的整体脚本。

     

..............

     

.....................

和主要的,

  

脚本对象中的内容

     

当您输入AppleScript语句时   脚本编辑器中的脚本窗口,您正在使用顶级脚本   宾语。除了之外,所有脚本对象定义都遵循相同的语法   顶级脚本对象没有标记其的语句   开始和结束。

     

脚本对象可以包含以下内容:

     

属性定义(可选):属性是标记的容器   哪个存储价值。

     

显式运行处理程序(可选):运行处理程序包含语句   运行脚本时AppleScript会执行。 (欲获得更多信息,   请参阅运行处理程序。)

     

隐式运行处理程序(可选):隐式运行处理程序包含   任何包含的处理程序或脚本对象之外的任何语句。

     

其他处理程序(可选):处理程序相当于a   子程序。 (有关详细信息,请参阅关于处理程序。)

     

其他脚本对象(可选):脚本对象可以包含   嵌套脚本对象,每个对象都被定义为顶级对象   脚本对象,除了嵌套的脚本对象被括起来   标记其开头和结尾的陈述。 (有关详细信息,请参阅脚本   对象。)

因此,简单来说,Application是一个包含Window的对象,它是一个包含Tab对象的对象.....

您需要从Window检索Application个对象/元素才能使用closeable

每个SBElementArray都应该有interface。你需要得到它。

实施例,

// The application's top-level scripting object.
@interface ChromeApplication : SBApplication

- (SBElementArray<ChromeWindow *> *) windows;

@property (copy, readonly) NSString *name;  // The name of the application.
@property (readonly) BOOL frontmost;  // Is this the frontmost (active) application?
@property (copy, readonly) NSString *version;  // The version of the application.

- (void) open:(NSArray<NSURL *> *)x;  // Open a document.
- (void) quit;  // Quit the application.
- (BOOL) exists:(id)x;  // Verify if an object exists.

@end

您应该检索- (SBElementArray<ChromeWindow *> *) windows;以使用closable。再次在Windows中你有标签数组等。

例如,在AppleScript中获取每个标签的URL和标题:

tell application "Google Chrome"

    set a to ""
    repeat with w in windows
        repeat with t in tab in w  // Getting tab object from window
            set a to a & linefeed & title of t & " -URL: " & URL of t
        end repeat
    end repeat

end tell

Swift中的等价物是:

import Cocoa
import ScriptingBridge


var chromeObject: AnyObject = SBApplication.init(bundleIdentifier: "com.google.Chrome")!

var f = chromeObject.windows() // get the windows from application
for i in f!
{
    var t = (i as AnyObject).tabs() // get the tabs from windows
    for j in t!
    {
        print(((j as AnyObject).title as String) + " -URL: " + ((j as AnyObject).url as String))
    }
}

希望它有所帮助!

答案 1 :(得分:-2)

来自SBApplication.init?(bundleIdentifier:)的文档:

  

返回值

     

SBApplication子类的初始化共享实例,表示包标识符为ident的目标应用程序。如果找不到这样的应用程序或者应用程序没有脚本接口,则返回nil

您应该检查init方法在强制解包前返回实例,例如:

if let chromeObject = SBApplication.init(bundleIdentifier: "com.google.Chrome") as? AnyObject {
    print(chromeObject.closeable)
}