【问题标题】:Swift and scriptingbridge object initializationSwift 和 scriptingbridge 对象初始化
【发布时间】:2014-07-27 18:30:46
【问题描述】:

我正在尝试编写一个用于快速控制 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, iTunesURLTrack, iTunesUserPlaylist, iTunesFolderPlaylist, iTunesBrowseVisual, iTunesWindow, iTunes , iTunes播放列表窗口;

例如,在 Objective-c 中,你会使用类似这样的东西来获取当前曲目

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

但我无法在 swift 中找到等价物。

【问题讨论】:

  • 当您执行println("\(iTunes.className)") 时,它会返回“ITunesApplication”
  • 编译器错误 - “AnyObject 没有名为 className 的成员”
  • 是的。我在测试中看到了这一点。我指出,尽管它给出了该错误,但它被归类为 iTunesApplication。我还可以建议您在问题中添加更多细节吗?关于您尝试解决此问题的方法以及如何导入 iTunes.h 文件等。我知道我希望 xcode 能够将其添加到头文件导入文件中,但我从来没有得到。
  • 我检查了对象是否响应挑战 iTunes PlayerState。它返回一个数字。同时,当我想引用 iTunes.h @class 表示的类时,会出现编译错误。很奇怪。
  • 请将代码添加到您收到回复的答案中以及您收到错误的代码中。这可以帮助任何想要查看此内容的人不要猜测您在做什么。这将鼓励答案。

标签: xcode itunes swift applescript-objc


【解决方案1】:

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

(iTunes as AnyObject).play()

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

【讨论】:

    【解决方案2】:

    我怀疑问题是没有导入 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) {
    
        }
    

    【讨论】:

    • @jQwierdy 这是一篇旧帖子,此后 swift 发生了变化,所以如果它现在确实抛出错误,我不会感到惊讶,但在发布时,一切都像我所说的那样工作。从那以后,我就很少使用 ScriptingBridge 了。主要是因为我没有必要,而且由于这篇文章的所有原因,使用它是如此痛苦。
    • @jQwierdy 为了让它再次工作,我所做的只是将 iTunes Var 行更改为:` let iTunes : AnyObject = SBApplication(bundleIdentifier: "com.apple.iTunes")!`
    • 你说得对,我做了一个愚蠢的评论——我很抱歉。愚蠢的我,我没有完全理解 AnyObject 作为 ObjC 的 ID 类型的含义——因为这意味着它是动态类型的。我的任何编译器都抛出了错误,但原因不同。对于那个很抱歉。你的回答很好。
    • @jQwierdy ,没问题。我自己去过那里
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      在我的 swift 项目中,我在使用生成的 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
      

      以及调用 swift 代码:

      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)")
                  }
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-01-03
        • 2020-03-29
        • 2013-06-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多