2012-08-14 19 views
5

Mountain Lion presentó new APIs, algunas de las cuales habíamos implementado como categorías en nuestro proyecto.Categorías condicionales en Mountain Lion

Por ejemplo, tenemos una categoría NSColor+CGColorAdditions que implementó CGColor y colorWithCGColor: para NSColor. Estos métodos han sido agregados en Mountain Lion.

Idealmente, nos gustaría utilizar estas categorías si el sistema operativo del cliente es más antiguo que Mountain Lion, y no usarlos si se trata de Mountain Lion. ¿Cómo podemos hacer esto? ¿O hay una mejor alternativa?

Respuesta

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

Gracias. ¿Dónde recomendarías poner este código de inicialización? ¿Se puede ejecutar estáticamente dentro de -say- el archivo de categoría? – hpique

+0

@hgpc quizás entre las primeras líneas de la aplicación: didFinishLaunchingWithOptions: method. –

+1

¿De verdad? Lo pondría en un método + carga. –

2

Pensé que también podría ser útil publicar lo que hice basándome en la respuesta de H2CO3.

NSColor+CGColorAdditions.m se convirtió en:

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

No estoy tan seguro de que quiera usar 'constructor' para esto, porque no está claro cuándo será llamado en relación con el tiempo de ejecución que se está configurando. A ['+ load'] (http://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/Reference/Reference.html#//apple_ref/doc/uid/20000050- carga) método de categoría es probablemente el lugar apropiado para hacer esto. –

+0

@ W'rkncacnter Hasta donde yo sé, las funciones del constructor se llaman antes que las principales. –

+1

@ H2CO3: Correcto - mi preocupación es que se llamen antes de que se haya construido el tiempo de ejecución, pero no estoy exactamente seguro de que eso ocurra. Tiene sentido que sea cuando se cargue libobjc, por lo que probablemente no sea un problema, pero '+ load' _is_ explícitamente para manipular las clases antes de main. –

Cuestiones relacionadas