Domanda

Sono solo imparare a usare ScriptingBridges. Ho fatto un metodo che sfuma lentamente il volume su iTunes, e vorrei farne una categoria in modo da poter effettuare le seguenti operazioni:

iTunesApplication* iTunes = [SBApplication applicationWithBundleIdentifier:@"com.apple.iTunes"];
[iTunes lowerVolume:50 speed:1];

Ho fatto un'altra categoria per NSSpeechSynthesizer che le opere, ma non posso ottenere questo uno a. Continuo a ricevere il seguente errore di generazione:

"_OBJC_CLASS_$_iTunesApplication", referenced from:
l_OBJC_$_CATEGORY_iTunesApplication_$_iTunesApplicationAdditions in iTunesApplication.o
objc-class-ref-to-iTunesApplication in iTunesApplication.o
ld: symbol(s) not found
collect2: ld returned 1 exit status

C'è qualcosa di speciale che posso fare per farlo funzionare dal momento che non possono includere i simboli?

Grazie,
Ryan Pendleton

UPDATE: Ho trovato una sola soluzione, che è al di sotto. Si tratta MethodSwizzling, quindi sono aperto a risposte migliori, ma per ora è tutto quello che ho.

È stato utile?

Soluzione

La soluzione che ho trovato è stato quello di utilizzare l'API runtime di Objective-C. Sono sicuro che c'è un modo migliore per organizzare questo, ma ecco come ho fatto:

Qui ci sono i miei file .h e .m per creare la categoria. Si noti come lowerVolume non è un metodo effettivo, ma una funzione C con argomenti id self e SEL _CMD. Noterete anche una funzione setupCategories. Chiameremo che più tardi.

// iTunes+Volume.h

#import <objc/runtime.h>
#import "iTunes.h"

void lowerVolume(id self, SEL _cmd, int dest, float speed);
void setupCategories();

@interface iTunesApplication (Volume)

- (void)lowerVolume:(int)dest speed:(float)speed;

@end

// iTunes+Volume.m

#import "iTunes+Volume.h"

void lowerVolume(id self, SEL _cmd, int dest, float speed)
{
    NSLog(@"Lower Volume: %i, %f", dest, speed);
}

void setupCategories()
{
    id object = [[SBApplication alloc] initWithBundleIdentifier:@"com.apple.iTunes"];
    Class class = [object class];
    [object release];

    class_addMethod(class, @selector(lowerVolume:speed:), (IMP)lowerVolume, "@:if");
}

Ora che ho fatto le funzioni, ho bisogno di aggiungerli in realtà alla classe ponte di scripting utilizzando il runtime API Objective-C. Farò questo in main.m per assicurarsi che i metodi sono pronti per essere utilizzati all'avvio del ciclo di esecuzione.

// main.m

#import <Cocoa/Cocoa.h>
#import "iTunes+Volume.h"

int main(int argc, char *argv[])
{
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];

    setupCategories();
    return NSApplicationMain(argc,  (const char **) argv);

    [pool drain];
}

Ora, posso utilizzare il mio metodo dove voglio finchè includo i file di intestazione:

- (void)mute
{
    iTunesApplication* iTunes = [[SBApplication alloc] initWithBundleIdentifier:@"com.apple.iTunes"];
    [iTunes lowerVolume:0 speed:1];
    [iTunes release];
}

Se tutto questo non ha senso, mi dica e io cercherò di spiegare meglio.

Altri suggerimenti

Credo che hai bisogno di includere -framework ScriptingBridge ai vostri argomenti gcc. Che ha ottenuto a compilare per me!

Come notato sopra, non si può fare facilmente una categoria a iTunesApplication perché non esiste in fase di compilazione, e anche perché il nome della classe runtime è ITunesApplication ( "I" maiuscola).

La soluzione migliore che ho trovato è quello di fare la tua categoria sulla classe che esiste, SBApplication. Ecco il codice che ho provato che funziona e fa quello che l'esempio originale stava cercando di fare:

//  SBApplication+Extensions.h

@import ScriptingBridge;

@interface SBApplication (Extensions)

- (void)lowerVolume:(int)dest speed:(float)speed;

@end

//  SBApplication+Extensions.m

#import "iTunes.h"
#import "SBApplication+Extensions.h"

@implementation SBApplication (Extensions)

- (void)lowerVolume:(int)dest speed:(float)speed
{
    NSLog(@"Lower Volume: %i, %f", dest, speed);
}

@end

// Caller, say in AppDelegate

#import "SBApplication+Extensions.h"

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{

    iTunesApplication *iTunesApp =
        [SBApplication applicationWithBundleIdentifier:@"com.apple.iTunes"];

    [iTunesApp lowerVolume:4 speed:3.3f];
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top