2014-06-06 10 views
5

Ich versuche, eine Anwendung für die schnelle Steuerung von iTunes zu schreiben. Aber beim Initialisieren der Anwendung gibt ein Objekt vom Typ AnyObject zurück, muss aber iTunesApplication.Swift und scriptingbridge Objekt Initialisierung

Dieses Objekt reagiert nicht auf Methoden und Variablen von iTunes. Wer weiß, wie es funktioniert?

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

Der iTunes.h Header enthält auch Klassen, die ich zugreifen müssen aber nicht. Diese Klassen verursachen einen Kompilierungsfehler, als ob sie nicht in einer iTunes.h deklariert sind.

Warum ist das passiert mir noch nicht klar ist.

Die ganze Liste von Klassen, die eine iTunes.h in über @class deklariert sind:

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

Zum Beispiel in Objective - c Sie so etwas wie diese verwenden würden, um den aktuellen Titel

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

Aber ich kann nicht ein Äquivalent in schnellen bekommen zu arbeiten.

+0

Wenn Sie 'println (" \ (iTunes.className) ")' es gibt "ITunesApplication" – markhunte

+0

Compiler-Fehler - "AnyObject hat kein Mitglied namens className" –

+0

Ja. Das habe ich bei meinen Tests gesehen. Ich habe darauf hingewiesen, dass obwohl es diesen Fehler gibt, es als ITunesApplication eingestuft wird. Kann ich Ihnen auch vorschlagen, dass Sie Ihrer Frage mehr Details hinzufügen? über das, was Sie versucht haben, dies zu lösen und wie Sie die iTunes.h-Datei usw. importieren. Ich weiß, dass ich erwartet hatte, dass xcode eine Header-Importdatei hinzufügen würde, aber ich bekam nie eine. – markhunte

Antwort

3

Ich vermuten, dass das Problem war, dass die iTunes.h Datei nicht importiert wurde. Daher werden die Methoden nicht abgeholt.

So habe ich eine -Bridging-header.h Datei.

Mein Projekt ist Name swiftItunesTest. so die -Bridging-header.h Datei heißt:

swiftItunesTest-Bridging-header.h

Innere dieses Ich legte die #import "iTunes.h" Linie

Und in der AppDelegate.swift Datei

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 
    } 


} 

die iTunesApplication (iTunes.) jetzt damit begonnen, die Methoden zu holen/Funktionen


Hier ist eine leicht aktualisierte Beispiel.

+0

@jQwierdy Dies ist ein alter Post und Swift hat sich seit dem geändert, so würde ich nicht überrascht sein, wenn es jetzt einen Fehler, aber zum Zeitpunkt der Veröffentlichung alle funktionierte, wie ich behaupte. Ich habe seitdem nicht viel mit ScriptingBridge gespielt. Hauptsächlich weil ich keine Notwendigkeit hatte und auch weil es so ein Schmerz war, aus all den Gründen diesen Beitrag zu verwenden. – markhunte

+0

@jQwierdy Alles, was ich getan habe, um das wieder zum Laufen zu bringen, war, die iTunes Var-Zeile auf "iTunes: AnyObject = SBApplication (bundleIdentifier:" com.apple.iTunes ") zu setzen!' – markhunte

+0

Du hast recht, ich habe einen Blödsinn gemacht Kommentar - Tut mir leid. Dumm von mir, ich habe die Bedeutung von AnyObject, das ObjCs ID-Typ ist, nicht vollständig verstanden - weil das bedeutet, dass es dynamisch getippt wird. Jeder meiner Compiler hat einen Fehler ausgegeben, aber das hatte einen anderen Grund. Das tut mir leid. Deine Antwort ist gut. – jQwierdy

7

In meinem schnellen Projekt hatte ich Probleme mit den Typen, die in der generierten iTunes.h-Datei definiert wurden (Verbindungsfehler und so).

Die Antwort von markhunte erklärt, dass Sie einen Verweis auf das Anwendungsobjekt erhalten können. Aber darüber hinaus habe ich Compilation/Linker-Fehler bekommen, wenn ich versuche, Instanzen von diesem Anwendungsobjekt zu erhalten.

In meinem schnellen Projekt habe ich am Ende eine objektive C-Wrapper-Klasse erstellt, die die iTunes-Typen als grundlegende Ziel-C-Typen (Arrays und Dictionary) darstellt und Methoden anpasst.

Meine Swift-Klassen verwenden diesen Wrapper anstelle der iTunes-Typen. So sieht

das Ziel C-Wrapper wie diese (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 

und den anrufenden 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)") 
      } 
     } 
    } 
} 
2

ich ein Python-Skript geschrieben Scripting-Brücke Header zu erzeugen, und dann automatisch Mach eine native Swift-Version. Auf diese Weise müssen Sie sich nicht mit dem Schreiben vollständiger Wrapper oder sogar mit einem Bridging-Header beschäftigen. Auch keine Sorge wegen Linker-Fehlern, da es komplett in Swift ist. https://github.com/garrett-davidson/SwiftingBridge/

1

Eine unelegante Art und Weise arbeiten, um das Problem zu tun ist, iTunes erklärt zu haben, wie ein SBApplication, dann, wenn Sie eine Funktion von iTunesApplication, gesenkten iTunes zu einem AnyObject nennen:

(iTunes as AnyObject).play() 

Hinweis, dass es Keine type-safety, wenn du das tust: Du könntest jede Funktion aufrufen, die in einem Objective-C-Header deklariert ist: es ist einfach nicht garantiert, dass sie in einer bestimmten Klasse implementiert ist, und somit wird das Programm zum Absturz gebracht.