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?
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
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.
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
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With