在分类中添加属性@property (nonatomic) id newProperty;
只会生成set和get方法,但不会生成成员变量的;若想实现在分类中添加属性@property (nonatomic) id newProperty;
就像在原类中添加属性一样的效果,可以通过运行时的关联引用来实现,但本文介绍一种不用关联引用来实现的方案,如下:
用NSObject的分类来进行演示;
一、 在NSObject(BYExtension)分类中给相应的属性添加@property,以方便打点调用:
如:
@property (nonatomic) id newProperty;
二、在分类文件中方法外面添加NSMutableDictionary *类型的静态态变量,用来存放所有实例的属性-值字典:
如:
static NSMutableDictionary * _warehouseProperty;
这里之所以要用可变字典,是为了方便存取,如果换成其它的容器,实现起来相当麻烦,所以要用字可变字典;
三、实现get和set方法:
如:
//给newProperty属性赋值
-(void)setNewProperty:(id)newProperty
{
// 确保_warehouseProperty可变字典存在且只创建一次
if (_warehouseProperty == nil) {
_warehouseProperty = [[NSMutableDictionary alloc] init];
}
// 为了实现分类中能添加多个属性,需要为每个实例维护一份存属性值的可变字典
if (_warehouseProperty[self] == nil) {
_warehouseProperty[self] = [[NSMutableDictionary alloc] init];
}
//nil不能存到字典中
if (newProperty != nil) {
//每个实例都有一个可变字典,用来存储不同属性的值,用属性名作键,属性值作值
_warehouseProperty[self][@"newProperty"] = newProperty;
}
}
//返回属性的值
-(id)newProperty
{
return _warehouseProperty[self][@"newProperty"];
}
四、实现NSCopying协议:
因为NSDictionary要求,作为Key的对象必须得遵守NSCopying协议,所以要该类实现NSCopying协议;
如:
接口文件:
@interface NSObject(BYExtension) <NSCopying> //因为要把该类的实例用作字典的键,所以需要实现NSCopying协议;
- (id)copyWithZone:(nullable NSZone *)zone;
实现文件:
//NSCopying协议的实现;因为要把该类的实例用作字典的键,所以需要实现NSCopying协议;
- (id)copyWithZone:(nullable NSZone *)zone
{
return self;
}
完成之后,整个分类的效果如下:
NSObject(BYExtension).h文件:
#import <Foundation/Foundation.h>
@interface NSObject(BYExtension) <NSCopying> //因为要把该类的实例用作字典的键,所以需要实现NSCopying协议;
@property (nonatomic) id newProperty;
- (id)copyWithZone:(nullable NSZone *)zone;
@end
NSObject(BYExtension).m文件:
#import "NSObject(BYExtension).h"
static NSMutableDictionary * _warehouseProperty; //用类存储属性值的字典
@implementation NSObject(BYExtension)
//NSCopying协议的实现;因为要把该类的实例用作字典的键,所以需要实现NSCopying协议;
- (id)copyWithZone:(nullable NSZone *)zone
{
return self;
}
//给newProperty属性赋值
-(void)setNewProperty:(id)newProperty
{
// 确保_warehouseProperty可变字典存在且只创建一次
if (_warehouseProperty == nil) {
_warehouseProperty = [[NSMutableDictionary alloc] init];
}
// 为了实现分类中能添加多个属性,需要为每个实例维护一份存属性值的可变字典
if (_warehouseProperty[self] == nil) {
_warehouseProperty[self] = [[NSMutableDictionary alloc] init];
}
//nil不能存到字典中
if (newProperty != nil) {
//每个实例都有一个可变字典,用来存储不同属性的值,用属性名作键,属性值作值
_warehouseProperty[self][@"newProperty"] = newProperty;
}
}
//返回属性的值
-(id)newProperty
{
return _warehouseProperty[self][@"newProperty"];
}
@end