6

我正在尝试编写一个用于快速控制 iTunes 的应用程序。但是在初始化应用程序时返回一个类型为 的对象AnyObject,而且必须是 iTunesApplication。

该对象不响应 iTunes 的方法和变量。谁知道如何使它工作?

var iTunes = SBApplication.applicationWithBundleIdentifier("com.apple.iTunes")

iTunes.h 标头还包含我需要访问但不能访问的类。这些类会导致编译错误,就好像它们不在声明的 iTunes.h 中一样。

为什么这会发生在我身上还不清楚。

通过@class 声明为 iTunes.h 的整个类列表:

@class iTunesPrintSettings, iTunesApplication, iTunesItem, iTunesAirPlayDevice, iTunesArtwork, iTunesEncoder, iTunesEQPreset, iTunesPlaylist, iTunesAudioCDPlaylist, iTunesLibraryPlaylist, iTunesRadioTunerPlaylist, iTunesSource, iTunesTrack, iTunesAudioCDTrack, iTunesFileTrack, iTunesSharedTrack, iTunes URLTrack, iTunesUserPlaylist, iTunesFolderPlaylist, iTunes Visual, iTunes Window, iTunes iTunes Playlist iTunesBrowserWindow;

例如,在 Objective-c 中,您将使用类似这样的方法来获取当前曲目

iTunesApplication *iTunes = [SBApplication applicationWithBundleIdentifier:@"com.apple.iTunes"];
NSLog(@"Current song is %@", [[iTunes currentTrack] name]);

但是我无法快速工作。

4

4 回答 4

7

在我的快速项目中,我在使用生成的 iTunes.h 文件中定义的类型时遇到了问题(链接错误等)。

markhunte 的回答解释说,您可以获得对应用程序对象的引用。但除此之外,在尝试从该应用程序对象获取实例时,我遇到了编译/链接器错误。

在我的 swift 项目中,我最终创建了一个目标 C 包装类,它将 iTunes 类型公开为基本的目标 C 类型(数组和字典),并调整方法。

我的 swift 类使用这个包装器而不是 iTunes 类型。

因此,目标 C 包装器看起来像这样(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

和调用快速代码:

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)")
            }
        }
    }
}
于 2014-06-14T00:09:00.903 回答
3

我怀疑问题是没有导入 iTunes.h 文件。因此,它是不被采用的方法。

所以我创建了一个 -Bridging-Header.h 文件。

我的项目名称为swiftItunesTest。所以 -Bridging-Header.h 文件被命名为:

swiftItunesTest-Bridging-Header.h

在这里面我放了#import "iTunes.h"线

AppDelegate.swift文件中

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
    }


}

iTunesApplication (iTunes.) 现在开始使用方法/功能


这是一个稍微更新的示例。

 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) {

    }
于 2014-06-10T17:25:35.703 回答
2

我编写了一个 Python 脚本来生成 Scripting Bridge 标头,然后自动制作一个原生 Swift 版本。这样您就不必编写完整的包装器,甚至不必使用桥接头。此外,不用担心链接器错误,因为它完全在 Swift 中。https://github.com/garrett-davidson/SwiftingBridge/

于 2015-06-27T17:39:02.713 回答
1

解决此问题的一种不优雅的方法是将iTunes声明为SBApplication,然后,当您从 调用函数时iTunesApplication,向下转换iTunesAnyObject

(iTunes as AnyObject).play()

请注意,如果您这样做,则没有类型安全性:您可以调用在任何 Objective-C 标头中声明的任何函数:它只是不能保证在特定类中实现,因此会使程序崩溃。

于 2016-01-25T19:53:08.617 回答