Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add BOOL property via a category [duplicate]

I am using a category NSAttributedString (Additions) and I really need a way to add a property that will be a BOOL (indicating whether the string is an HTML tag or not). I know that categories should not have properties but that's the the way I need to do it. I tired writing my own getters and setters but it didn't work. How can this work?

like image 216
Mace Avatar asked Mar 19 '12 19:03

Mace


4 Answers

For the sake of completeness, this is how I got this to work:

@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
like image 146
Joshua Goossen Avatar answered Oct 20 '22 06:10

Joshua Goossen


Categories can have read-only properties, you just can't add instance variables with them (well, you can, sort of - see associative references).

You can add a category method (presented by a read only property) isHTMLTag which would return a BOOL, you would just have to calculate if it was an HTML tag each time within that method.

If you are asking for a way to set the BOOL value then you'll need to use associated references (objc_setAssociatedObject) which I've never used so don't feel qualified to answer on in any more detail.

like image 29
jrturton Avatar answered Oct 20 '22 06:10

jrturton


My solution without the need of an object key and a little bit easier to read syntax

NSString+Helper.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
like image 2
Rikco Avatar answered Oct 20 '22 05:10

Rikco


Probably very late in this world, when swift is already sweeping objective c. Anyhow, with Xcode 8, you can also use class properties, instead of using associative references.

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

@implementation
static id *__myProperty = nil;

+ (id)myProperty {
    return __myProperty;
}

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

@end

From the Xcode 8 release notes:

Objective-C now supports class properties, which interoperate with Swift type properties. They are declared as: @property (class) NSString *someStringProperty;. They are never synthesized. (23891898)

like image 2
iHS Avatar answered Oct 20 '22 05:10

iHS