2012-03-19 4 views
16

Sto usando una categoria NSAttributedString (Additions) e ho davvero bisogno di un modo per aggiungere una proprietà che sarà una BOOL se la stringa è tag HTML o meno. So che le categorie non dovrebbero avere proprietà ma questo è il modo in cui ho bisogno di farlo. Sono stanco di scrivere i miei getter e setter ma non ha funzionato. Qualcuno sa come funziona?Come aggiungere la proprietà BOOL a una categoria?

+0

possibile duplicato di [Objective-C: Property in Category] (http: // stackoverflow.it/questions/8733104/objective-c-property-in-category) –

+0

Pubblica il codice per i tuoi getter e setter! – paulmelnikow

risposta

4

Le categorie possono avere proprietà di sola lettura, non è possibile aggiungere semplicemente variabili di istanza con esse (beh, è ​​possibile, una sorta di - vedere riferimenti associativi).

È possibile aggiungere un metodo di categoria (presentato da una proprietà di sola lettura) isHTMLTag che restituirebbe un BOOL, si dovrebbe solo calcolare se si trattasse di un tag HTML ogni volta all'interno di tale metodo.

Se ti stai chiedendo di un modo per impostare il valore BOOL allora avrete bisogno di usare i riferimenti associati (objc_setAssociatedObject) che non ho mai usato in modo non si sentono qualificati per rispondere a qualsiasi più in dettaglio.

+1

Utilizzo dei riferimenti associati funzionanti! Grazie – Mace

+0

Ti dispiacerebbe condividere come hai fatto a farlo funzionare? –

+3

@Mace - puoi accettare la risposta di jrturton e aggiungere i dettagli da Joshua o accettare la risposta di Joshua ...? –

0

Se è davvero necessario aggiungere una proprietà, è necessario creare una sottoclasse anziché aggiungere una categoria.

+1

A volte questo non è possibile. Ad esempio, se il codice che crea l'istanza di detta classe non è accessibile (ad esempio in una libreria statica). –

38

Per ragioni di completezza, questo è come ho ottenuto questo lavoro:

@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

E la gestione della memoria? L'istanza NSNumber viene mantenuta da solo all'interno del metodo -setBoolProperty :. Devo rilasciarlo in qualche modo? Da runtime.h: "@param value Il valore da associare alla chiave per l'oggetto Passa nil per cancellare un'associazione esistente." Ma non posso ignorare dealloc in una categoria. – igrek

+0

Trovato una risposta qui: http://stackoverflow.com/questions/10842829/will-an-associated-object-be-released-automatically/10843510#10843510 Viene rilasciato correttamente – igrek

+0

A proposito, è possibile omettere l'utilizzo di costanti aggiuntive per chiavi; invece, usa @selector (boolProperty) invece di ObjectTagKey, che fornirà esattamente ciò di cui hai bisogno – igrek

0

La mia soluzione, senza la necessità di una chiave oggetto e un po 'più facile da leggere la sintassi

NSString + Guida 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

Probabilmente molto tardi in questo mondo, quando Swift è già spazzando obiettivo c. In ogni caso, con Xcode 8, puoi anche usare le proprietà della classe, invece di usare riferimenti associativi.

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

@implementation 
static id *__myProperty = nil; 

+ (id)myProperty { 
    return __myProperty; 
} 

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

@end

Dalle Xcode 8 note di rilascio:

Objective-C supporta ora proprietà della classe, che interagiscono con proprietà del tipo di Swift. Sono dichiarati come: @property (class) NSString * someStringProperty ;. Non sono mai sintetizzati. (23891898)

0

Swift 3:

Utilizzando questo metodo, è possibile aggiungere qualsiasi nuova proprietà (in questo caso aggiungere valore Bool) alla classe emozionante.

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) 
     } 
    } 
}