2014-06-06 13 views
5

Próbuję napisać wniosek o szybką kontrolę iTunes. Ale podczas inicjowania aplikacji zwraca obiekt typu AnyObject, ale musi mieć aplikację iTunesApplication.Inicjalizacja obiektu Swift i scriptingbridge

Ten obiekt nie reaguje na metody i zmienne iTunes. Kto wie, jak to działa?

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

Nagłówek iTunes.h zawiera również klasy, do których muszę uzyskać dostęp, ale nie można ich uzyskać. Te klasy powodują błąd kompilacji, tak jakby nie znajdowały się w zadeklarowanym pliku iTunes.h.

Dlaczego to się ze mną dzieje, nie jest jeszcze jasne.

Cała lista klas, które są uznane za iTunes.h via @class:

iTunesPrintSettings @class, iTunesApplication, iTunesItem, iTunesAirPlayDevice, iTunesArtwork, iTunesEncoder, iTunesEQPreset, iTunesPlaylist, iTunesAudioCDPlaylist, iTunesLibraryPlaylist, iTunesRadioTunerPlaylist, iTunesSource , iTunesTrack, iTunesAudioCDTrack, iTunesFileTrack, iTunesSharedTrack, iTunesURLTrack, iTunesUserPlaylist, iTunesFolderPlaylist, iTunesVisual, iTunesWindow, iTunesBrowserWindow, iTunesEQWindow, iTunesPlaylistWindow;

Na przykład w Objective - C należałoby użyć coś takiego dostać bieżącej ścieżki

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

Ale nie mogę dostać równowartość w szybkich do pracy.

+0

Po wykonaniu polecenia 'println (" \ (iTunes.className) ") zwraca komunikat" ITunesApplication " – markhunte

+0

Błąd kompilatora -" AnyObject nie ma członka o nazwie className " –

+0

Tak. Widziałem to w moich testach. Wskazałem, że mimo że podaje ten błąd, jest on klasyfikowany jako aplikacja ITunesApplication. czy mogę również zasugerować, by dodać więcej szczegółów do swojego pytania. o tym, co próbowaliście rozwiązać i jak importujesz plik iTunes.h itd. Wiem, że dla jednego oczekiwałem, że xcode zaoferuje dodanie go do pliku importu nagłówka, ale nigdy go nie dostałem. – markhunte

Odpowiedz

3

Podejrzewałem, że problem polegał na tym, że plik iTunes.h nie został zaimportowany. Dlatego też metody nie są odbierane.

Stworzyłem plik -Bridging-Header.h.

Mój projekt nazywa się swiftItunesTest. więc plik -Bridging-header.h nazwie:

swiftItunesTest-pomostowe header.h

Wewnątrz tego umieściłem linię

#import "iTunes.h" A w AppDelegate.swift pliku

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 
    } 


} 

W iTunesApplication (iTunes). teraz zaczął uczyć się metody/funkcji


Oto nieco zaktualizowany przykład.

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

    } 
+0

@jQwierdy jest to stary post i szybko zmieniło się od tego czasu, więc nie byłbym zaskoczony, gdyby wystąpił błąd teraz, ale w momencie opublikowania wszystko działało tak jak ja. Od tego czasu nie grałem zbyt wiele w ScriptingBridge. Głównie dlatego, że nie miałam potrzeby, a także dlatego, że był taki trudny do użycia ze wszystkich powodów, dla których powstał ten post. – markhunte

+0

@jQwierdy Wszystko, co zrobiłem, aby znów zadziałało, to zmiana linii iTunes Var na: 'let iTunes: AnyObject = SBApplication (bundleIdentifier:" com.apple.iTunes ")! – markhunte

+0

Masz rację, zrobiłem głupiego komentarz - przykro mi z tego powodu. Głupi ze mnie, nie zrozumiałem w pełni znaczenia AnyObject jako typu ID ObjC - ponieważ oznacza to, że jest on wpisywany dynamicznie. Każdy mój kompilator zgłosił błąd, ale z innego powodu. Przepraszam za to. Twoja odpowiedź jest dobra. – jQwierdy

7

W moim szybkim projekcie miałem problemy z używaniem typów zdefiniowanych w wygenerowanym pliku iTunes.h (łączenie błędów i innych).

Odpowiedź od markhunte wyjaśnia, że ​​można uzyskać odniesienie do obiektu aplikacji. Poza tym podczas próby uzyskania wystąpień z tego obiektu aplikacji pojawiały się błędy kompilacji/łącznika.

W moim szybkim projekcie doszedłem do stworzenia obiektywnej klasy C, która ujawnia typy iTunes jako podstawowy cel typów C (tablice i słownika) oraz adaptuje metody.

Moje szybkie klasy używają tego opakowania zamiast plików iTunes.

więc, celem C wrapper wygląda następująco (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 

i wzywającą kod 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)") 
      } 
     } 
    } 
} 
2

Napisałem skrypt Pythona do generowania nagłówków Scripting Bridge i następnie automatycznie stworzyć natywną wersję Swift. W ten sposób nie musisz zajmować się pisaniem pełnych obwolut, ani nawet użyciem Nagłówka pomostowego. Nie martw się też Linker Errors, ponieważ jest całkowicie w Swift. https://github.com/garrett-davidson/SwiftingBridge/

1

nieeleganckie sposób zrobić obejścia problemu jest mieć iTunes zadeklarowane jako SBApplication, a następnie, po wywołaniu funkcji z iTunesApplication, przygnębiony iTunes do AnyObject:

(iTunes as AnyObject).play() 

pamiętać, że istnieje bez zabezpieczenia, jeśli to zrobisz: możesz wywołać dowolną funkcję zadeklarowaną w dowolnym nagłówku Objective-C: nie można jej zagwarantować, że zostanie zaimplementowana w konkretnej klasie, a zatem spowoduje awarię programu.

Powiązane problemy