1.category中添加属性
category里面是没法直接添加属性的,但是通过runtime的方式可以实现。主要使用objc_setAssociatedObject,objc_getAssociatedObject生成要添加属性的set,get方法。
例子:
.h文件
@property (nonatomic, readonly) NSString *name;
.m文件
- (void)setName:(NSString *)name
{
objc_setAssociatedObject(self, @"username", name,OBJC_ASSOCIATION_RETAIN_NONATOMIC );
}
- (NSString *)name
{
NSString *str=objc_getAssociatedObject(self, @"username");
return str;
}
2.方法的交换
当自己创建一个功能的方法,在项目中多次引用,当项目需求改变时,在不改变旧的项目前提下(也就是不变改原来的实现),需要使用另一个功能代替这个功能。
注意:交换两个方法的实现一般写在类的load方法里面,不写在initialize方法里。因为load方法只在程序运行前加载一次,而initialize方法会在类或者子类在第一次使用的时候调用,当有分类的时候会调用多次。
例子:
在category的.m文件
+ (void)load
{
[super load];
if(![self respondsToSelector:@selector(initWithCoder:)])return;
Method imp = class_getInstanceMethod([self class], @selector(initWithCoder:));
Method myImp = class_getInstanceMethod([self class], @selector(myInitWithCoder:));
method_exchangeImplementations(imp, myImp);
}
- (void)myInitWithCoder:(NSCoder *)aDecode
{
[self myInitWithCoder:aDecode];
if(self){
NSLog(@"已经交换成功");
}
}
3.数据转模型
一般情况下我们拿到的后台数据都是字典,拿到数据时我们要把它转成模型对象使用。
当对象数据很少的时候,我们可以写出字典的键值,直接转换。
当数据多的时候,我们可以用kvc键值编码的方式批量转换,但是当字典中的键,在对象找不到对应的属性的时候,要直接报错。
例子:
+ (NSArray *)propertyList
{
unsigned int count=0;
//获取属性列表
objc_property_t *list=class_copyPropertyList(self, &count);
NSMutableArray *array=[NSMutableArray arrayWithCapacity:count];
for (int i=0; i<count;i++)
{
objc_property_t p=list[i];
//获取属性名
const char *name=property_getName(p);
[array addObject:[NSString stringWithUTF8String:name]];
}
free(list);
return array.copy;
}
+ (instancetype)objectWithDict:(NSDictionary *)dict
{
id object=[[self alloc]init];
NSArray *properties=[self propertyList];
for (NSString *key in properties) {
if (dict[key]!=nil) {
//用kvc设置值
[object setValue:dict[key] forKey:key];
}
}
return object;
}