Я использую категорию NSAttributedString (Additions)
и мне действительно нужен способ добавить свойство, которое будет BOOL
(указывая, является ли строка тегом HTML или нет). Я знаю, что у категорий не должно быть свойств, но именно так, как мне нужно. Я устал писать свои собственные методы получения и установки, но это не сработало. Как это может работать?
Добавить BOOL недвижимость через категорию
Ответ 1
Для полноты, вот как я получил это для работы:
@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
Ответ 2
Категории могут иметь свойства только для чтения, вы просто не можете добавлять к ним переменные экземпляра (ну, вы можете, вроде - см. ассоциативные ссылки).
Вы можете добавить метод категории (представленный только для свойства чтения) isHTMLTag
, который вернет BOOL, вам просто нужно будет вычислить, был ли он HTML-тегом каждый раз в этом методе.
Если вы запрашиваете способ установить значение BOOL, вам нужно будет использовать связанные ссылки (objc_setAssociatedObject
), которые я никогда не использовал, поэтому не чувствуйте себя готовыми ответить более подробно.
Ответ 3
Мое решение без необходимости использовать ключ объекта и немного легче читать синтаксис
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
Ответ 4
Если вам действительно нужно добавить свойство, тогда вы должны создать подкласс вместо добавления категории.
Ответ 5
Возможно, очень поздно в этом мире, когда стремительный уже приближается к цели. Во всяком случае, с помощью Xcode 8 вы также можете использовать свойства класса, вместо использования ассоциативных ссылок.
@interface ClassName (CategoryName)
@property (class) id myProperty;
@end
@implementation
static id *__myProperty = nil;
+ (id)myProperty {
return __myProperty;
}
+ (void)setMyProperty:(id)myProperty {
__myProperty = myProperty;
}
@end
Из примечаний к выпуску Xcode 8:
Objective-C теперь поддерживает свойства класса, которые взаимодействуют с Свойства Swift. Они объявляются как: @property (класс) NSString * someStringProperty;. Они никогда не синтезируются. (23891898)
Ответ 6
Свифт 3:
Используя этот метод, вы можете добавить любое новое свойство (здесь добавить значение Bool) в захватывающий класс.
import ObjectiveC
private var xoAssociationKey: UInt8 = 0
extension <ClassName> {
var <propertyName>: Bool! {
get {
return objc_getAssociatedObject(self, &xoAssociationKey) as? Bool ?? false
}
set(newValue) {
objc_setAssociatedObject(self, &xoAssociationKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
}
}
}