2012-08-14 21 views
5

Mountain Lion eingeführt new APIs, von denen wir einige als Kategorien in unserem Projekt implementiert hatten.Bedingte Kategorien in Mountain Lion

Für Beispiele haben wir eine Kategorie NSColor+CGColorAdditions, die CGColor und colorWithCGColor: für NSColor implementiert. Diese Methoden wurden in Mountain Lion hinzugefügt.

Idealerweise möchten wir diese Kategorien verwenden, wenn das Client-Betriebssystem älter als Mountain Lion ist, und sie nicht verwenden, wenn es Mountain Lion ist. Wie können wir das tun? Oder gibt es eine bessere Alternative?

Antwort

7
NSColor *_NSColor_colorWithCGColor_(Class self, SEL cmd, CGColorRef cgColor) 
{ 
    // make an NSColor outta `cgColor` and return it 
    return nsColor; 
} 

// inside some initialization code 

if ([[NSColor class] respondsToSelector:@selector(colorWithCGColor:)]) { 
    // on ML, don't do anything 
} else { 
    // older system, add your own category 
    class_addMethod(objc_getMetaClass("NSColor"), @selector(colorWithCGColor:), (IMP)_NSColor_colorWithCGColor_, "@@:@"); 
} 
+0

Dank. Wo würdest du diesen Initialisierungscode empfehlen? Kann es innerhalb der Kategoriedatei statisch ausgeführt werden? – hpique

+0

@hgpc vielleicht unter den ersten Zeilen der Anwendung: didFinishLaunchingWithOptions: Methode. –

+1

Wirklich? Ich würde es in eine + load-Methode einfügen. –

2

Ich dachte, es könnte auch hilfreich sein zu posten, was ich getan habe basierend auf H2CO3 Antwort.

NSColor+CGColorAdditions.m wurde:

static CGColorRef _NSColor_CGColor_(Class self, SEL cmd) { 
    return nil; // TODO: Do something 
} 

static NSColor* _NSColor_colorWithCGColor_(Class self, SEL cmd, CGColorRef aColor) { 
    return nil; // TODO: Do something  
} 

__attribute__((constructor)) 
static void initialize_NSColor_CGColorAdditions() { 
    if (![[NSColor class] respondsToSelector:@selector(colorWithCGColor:)]) { 
     class_addMethod(objc_getMetaClass("NSColor"), @selector(colorWithCGColor:), (IMP)_NSColor_colorWithCGColor_, "@@:@"); 
    } 
    if (![[NSColor class] instancesRespondToSelector:@selector(CGColor)]) { 
     class_addMethod(objc_getClass("NSColor"), @selector(CGColor), (IMP)_NSColor_CGColor_, "@@:"); 
    } 
} 
+0

Ich bin mir nicht sicher, ob du 'constructor' dafür benutzen willst, weil es nicht klar ist, wann es in Bezug auf die zu erstellende Laufzeit aufgerufen wird. A ['+ load'] (http://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/Reference/Reference.html#//apple_ref/doc/uid/20000050- Die Methode load) category ist wahrscheinlich der geeignete Ort dafür. –

+0

@ W'rkncancnter Soweit ich weiß, werden Konstruktorfunktionen vor main aufgerufen. –

+1

@ H2CO3: Richtig - meine Sorge ist, dass sie aufgerufen werden, bevor die Laufzeit erstellt wurde, aber ich bin mir nicht sicher, wann das passiert. Es macht Sinn, dass es sein würde, wenn libobjc geladen wird, also ist dies wahrscheinlich kein Problem, aber '+ load' _ist_ explizit für das Fiedeln mit Klassen vor main. –