I'm trying out Apple's Scripting Bridge to interact with Google Chrome. I've started with the code in https://stackoverflow.com/a/24147285
I have created .h
file by using sdef
and sdp
commands.
I have included the file and also created the bridging header and imported chrome's header file in bridging header. But the problem is with using the header in Swift. The code is old and Swift has changed a lot.
My Swift file:
import Cocoa
import ScriptingBridge
var chromeObject = SBApplication.init(bundleIdentifier: "com.google.Chrome")! as AnyObject
print(chromeObject.closeable)
I'm getting an error saying
fatal error: unexpectedly found nil while unwrapping an Optional value
What am I doing wrong?
SBApplication
returns Application object. You can see different interface
s in .h
file.
@interface ChromeApplication : SBApplication
@interface ChromeWindow : SBObject <ChromeGenericMethods>
@interface ChromeApplication (ChromiumSuite)
@interface ChromeTab : SBObject <ChromeGenericMethods>
@interface ChromeBookmarkFolder : SBObject <ChromeGenericMethods>
@interface ChromeBookmarkItem : SBObject <ChromeGenericMethods>
So, SBApplication
returns you ChromeApplication
. You can call any properties defined inside ChromeApplication
. Try it yourself. You won't get any error.
The problem is you are calling closeable
which is part of ChromeWindow
.
From Apple Documentation:
AppleScript and Objects
AppleScript is an object-oriented language. When you write, compile, and execute scripts, everything you work with is an object. An object is an instantiation of a class definition, which can include properties and actions. AppleScript defines classes for the objects you most commonly work with, starting with the top-level script object, which is the overall script you are working in.
..............
.....................
and the main thing,
What Is in a Script Object
When you enter AppleScript statements in script window in Script Editor, you are working in a top-level script object. All script object definitions follow the same syntax, except that a top-level script object does not have statements marking its beginning and end.
A script object can contain the following:
Property definitions (optional): A property is a labeled container in which to store a value.
An explicit run handler (optional): A run handler contains statements AppleScript executes when the script is run. (For more information, see run Handlers.)
An implicit run handler (optional): An implicit run handler consists of any statements outside of any contained handlers or script objects.
Additional handlers (optional): A handler is the equivalent of a subroutine. (For details, see About Handlers.)
Additional script objects (optional): A script object can contain nested script objects, each of which is defined just like a top-level script object, except that a nested script object is bracketed with statements that mark its beginning and end. (For details, see Script Objects.)
So, in simple terms, Application
is an object which contains Window
which is an object which contains Tab
object.....
You need to retrieve Window
object/element from Application
to use closeable
.
You should have SBElementArray
in every interface
. You need to get that.
Example,
// 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
You should retrieve - (SBElementArray<ChromeWindow *> *) windows;
to use closable
. Again in windows you have tabs array, etc.
For example, In AppleScript to get URL and title of every tabs:
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
The equivalent in Swift would be:
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))
}
}
Hope it helps!