2012-03-19 11 views
16

Estoy usando una categoría NSAttributedString (Adiciones) y realmente necesito una forma de agregar una propiedad que será un BOOL si la cadena es una etiqueta HTML o no. Sé que las categorías no deberían tener propiedades, pero así es como debo hacerlo. Me cansé de escribir mis propios getters y setters, pero no funcionó. Alguien sabe una forma de cómo esto funcionaría?¿Cómo agregar la propiedad BOOL a una categoría?

+0

posible duplicado de [Objective-C: Propiedad en la categoría] (http: // stackoverflow.com/questions/8733104/objective-c-property-in-category) –

+0

¡Publique el código para sus captadores y establecedores! – paulmelnikow

Respuesta

4

Las categorías pueden tener propiedades de solo lectura, simplemente no puede agregar variables de instancia con ellas (bueno, puede, por ejemplo, ver referencias asociativas).

Puede agregar un método de categoría (presentado por una propiedad de solo lectura) isHTMLTag que devolvería un BOOL, solo tendría que calcular si se trataba de una etiqueta HTML cada vez dentro de ese método.

Si está pidiendo una manera de establecer el valor BOOL entonces usted tendrá que utilizar referencias asociadas (objc_setAssociatedObject) que nunca he usado así que no se siente calificado para responder sobre con mayor detalle.

+1

¡Se trabajó con referencias asociadas! Gracias – Mace

+0

¿Le importaría compartir cómo realmente lo hizo funcionar? –

+3

@Mace - ¿puedes aceptar la respuesta de jrturton y agregar los detalles de Joshua, o aceptar la respuesta de Joshua ...? –

0

Si realmente necesita agregar una propiedad, debe crear una subclase en lugar de agregar una categoría.

+1

A veces eso no es posible. Por ejemplo, si el código que crea la instancia de dicha clase no es accesible (por ejemplo, en una biblioteca estática). –

38

En aras de la exhaustividad, esto es cómo llegué a esto funcione:

@interface

@interface ClassName (CategoryName) 
@property (readwrite) BOOL boolProperty; 
@end 

@implementation

#import <objc/runtime.h> 

static char const * const ObjectTagKey = "ObjectTag"; 
@implementation ClassName (CategoryName) 
- (void) setBoolProperty:(BOOL) property 
{ 
    NSNumber *number = [NSNumber numberWithBool: property]; 
    objc_setAssociatedObject(self, ObjectTagKey, number , OBJC_ASSOCIATION_RETAIN); 
} 

- (BOOL) boolProperty 
{ 
    NSNumber *number = objc_getAssociatedObject(self, ObjectTagKey); 
    return [number boolValue]; 
} 
@end 
+0

¿Qué hay de la gestión de memoria? La instancia de NSNumber se conserva por sí misma dentro del método -setBoolProperty :. ¿Debo liberarlo de alguna manera? Desde runtime.h: "@ param value El valor para asociar con la clave de un objeto. Pase nil para borrar una asociación existente". Pero no puedo anular dealloc en una categoría. – igrek

+0

Encontró una respuesta aquí: http://stackoverflow.com/questions/10842829/will-an-associated-object-be-released-automatically/10843510#10843510 Se lanzó correctamente – igrek

+0

Por cierto, puede omitir el uso de constantes adicionales para Llaves; en su lugar, simplemente use @selector (boolProperty) en lugar de ObjectTagKey, que proporcionará exactamente lo que necesita – igrek

0

Mi solución sin la necesidad de una clave de objeto y una sintaxis un poco más fácil de leer

NSString + Ayuda er.h

#import <Foundation/Foundation.h> 

@interface NSString (Helper) 

@property (nonatomic, assign) BOOL isHTML; 

@end 

NSString + helper.h

#import "NSString+Helper.h" 
#import "objc/runtime.h" 

@implementation NSString (Helper) 

- (void)setIsHTML:(BOOL)isHTML 
{ 
    NSNumber *isHTMLBool = [NSNumber numberWithBool:isHTML]; 
    objc_setAssociatedObject(self, @selector(isHTML), isHTMLBool, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 
} 

- (BOOL)isHTML 
{ 
    NSNumber *isHTMLBool = objc_getAssociatedObject(self, @selector(isHTML)); 
    return isHTMLBool.boolValue; 
} 

@end 
0

Probablemente muy tarde en este mundo, cuando ya se está barriendo rápidamente objetivo c. De todos modos, con Xcode 8, también puede usar propiedades de clase, en lugar de usar referencias asociativas.

@interface ClassName (CategoryName) 
    @property (class) id myProperty; 
@end 

@implementation 
static id *__myProperty = nil; 

+ (id)myProperty { 
    return __myProperty; 
} 

+ (void)setMyProperty:(id)myProperty { 
    __myProperty = myProperty; 
} 

@end

De las notas de la versión Xcode 8:

Objective-C ahora es compatible con las propiedades de clase, los cuales interactúan con propiedades de tipo Swift. Se declaran como: @property (clase) NSString * someStringProperty ;. Ellos nunca son sintetizados. (23891898)

0

Swift 3:

El uso de este método, se puede añadir cualquier nueva propiedad (en este caso agregar valor Bool) a la clase emocionante.

import ObjectiveC 

private var xoAssociationKey: UInt8 = 0 

extension <ClassName> { 
    var <propertyName>: Bool! { 
     get { 
      if let returnVal = objc_getAssociatedObject(self, &xoAssociationKey) as? Bool{ 
       return returnVal 
      }else{ 
       return false 
      } 

     } 
     set(newValue) { 

      objc_setAssociatedObject(self, &xoAssociationKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN) 
     } 
    } 
} 
Cuestiones relacionadas