Swift and scriptingbridge object initialization

孤者浪人 提交于 2019-12-02 21:20:13

In my swift project , I had issues with using the types defined in the generated iTunes.h file (linking errors and such).

The answer from markhunte explains that you can obtain a reference to the application object. But beyond that, I was getting compilation/linker errors when trying to obtain instances from that application object.

In my swift project, I ended up creating an objective C wrapper class that exposes the iTunes types as basic objective C types (arrays and dictionary), and adapts methods as well.

My swift classes use this wrapper instead of the iTunes types.

So, the objective C wrapper looks like this (redux):

#import "ITunesBridgex.h"
#import "iTunes.h"

@interface ITunesBridgex(){
    iTunesApplication *_iTunesApplication;
    iTunesSource* _iTunesLibrary;
}
@end
@implementation ITunesBridgex

-(id)init {
    self = [super init];
    if (self) {
        _iTunesApplication = [SBApplication applicationWithBundleIdentifier:@"com.apple.iTunes"];
        NSArray *sources = [_iTunesApplication sources];
        for (iTunesSource *source in sources) {
            if ([source kind] == iTunesESrcLibrary) {
                _iTunesLibrary = source;
                break;
            }
        }
    }
    return self;
}

- (NSDictionary*) currentTrack {
    iTunesTrack* track = _iTunesApplication.currentTrack;
    if (!track)
        return nil;
    NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys: track.name, @"title", nil];
    return dict;
}

@end

and the calling swift code:

import Foundation
import Cocoa

class ITunesBridgeSimple {

    var iTunesBridgex: ITunesBridgex

    init(){
        iTunesBridgex = ITunesBridgex()
        self.updateFromCurrentTrack()
    }
    func updateFromCurrentTrack() {
        if let track = self.currentTrack {
            if let title : AnyObject = track.objectForKey("title"){
                println("Current track: \(title)")
            }
        }
    }
}

I suspected that the problem was that the iTunes.h file was not being imported. Therefore it's methods where not being picked up.

So I created a -Bridging-Header.h file.

My Project is name swiftItunesTest. so the -Bridging-Header.h file is named:

swiftItunesTest-Bridging-Header.h

Inside of this I placed the #import "iTunes.h" line

And in the AppDelegate.swift file

import Cocoa
 import Appkit
 import ScriptingBridge





class AppDelegate: NSObject, NSApplicationDelegate {

    @IBOutlet var window: NSWindow


    func applicationDidFinishLaunching(aNotification: NSNotification?) {
        var iTunes : AnyObject = SBApplication.applicationWithBundleIdentifier("com.apple.iTunes")

        iTunes.playpause()


    }

    func applicationWillTerminate(aNotification: NSNotification?) {
        // Insert code here to tear down your application
    }


}

The iTunesApplication (iTunes.) now started to pick up the methods/functions


Here is a slightly updated example.

 func applicationDidFinishLaunching(aNotification: NSNotification) {
        let iTunes : AnyObject = SBApplication(bundleIdentifier: "com.apple.iTunes")!

        iTunes.playpause()


          guard let currentTrack: AnyObject =  iTunes.currentTrack!.name else {

             print("No Tracks Playing")
             return
       }
          print("\(currentTrack)")

    }

    func applicationWillTerminate(aNotification: NSNotification) {

    }

I wrote a Python script to generate Scripting Bridge headers and then automatically make a native Swift version. That way you don't have to deal with writing full wrappers or even using a Bridging Header. Also, no worry of Linker Errors because it's completely in Swift. https://github.com/garrett-davidson/SwiftingBridge/

An inelegant way to do work around the issue is to have iTunes declared as an SBApplication, then, when you call a function from iTunesApplication, downcast iTunes to an AnyObject:

(iTunes as AnyObject).play()

Note that there is no type-safety if you do this: you could call any function declared in any Objective-C header: it's just not guaranteed to be implemented in a specific class, and thus will crash the program.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!