runtime的应用(仅供参考)

1.归档和解档

- (void)encodeWithCoder:(NSCoder*)aCoder{

unsignedintoutCount =0;

Ivar*vars =class_copyIvarList([selfclass], &outCount);

for(inti =0; i < outCount; i ++) {

Ivarvar = vars[i];

constchar*name =ivar_getName(var);

NSString*key = [NSStringstringWithUTF8String:name];

//注意kvc的特性是,如果能找到key这个属性的setter方法,则调用setter方法

//如果找不到setter方法,则查找成员变量key或者成员变量_key,并且为其赋值

//所以这里不需要再另外处理成员变量名称的“_”前缀

idvalue = [selfvalueForKey:key];

[aCoderencodeObject:valueforKey:key];

}

free(vars);

}

- (nullableinstancetype)initWithCoder:(NSCoder*)aDecoder{

if(self= [superinit]) {

unsignedintoutCount =0;

Ivar*vars =class_copyIvarList([selfclass], &outCount);

for(inti =0; i < outCount; i ++) {

Ivarvar = vars[i];

constchar*name =ivar_getName(var);

NSString*key = [NSStringstringWithUTF8String:name];

idvalue = [aDecoderdecodeObjectForKey:key];

[selfsetValue:valueforKey:key];

}

free(vars);

}

returnself;

}

2.字典转模型 或者 模型转字典

//字典转模型

+(id)objectWithKeyValues:(NSDictionary*)aDictionary{

idobjc = [[selfalloc]init];

for(NSString*keyinaDictionary.allKeys) {

idvalue = aDictionary[key];

/*判断当前属性是不是Model*/

objc_property_tproperty =class_getProperty(self, key.UTF8String);

unsignedintoutCount =0;

objc_property_attribute_t*attributeList =property_copyAttributeList(property, &outCount);

objc_property_attribute_tattribute = attributeList[0];

NSString*typeString = [NSStringstringWithUTF8String:attribute.value];

if([typeStringisEqualToString:@"@\"TestModel\""]) {

value = [selfobjectWithKeyValues:value];

}

/**********************/

//生成setter方法,并用objc_msgSend调用

NSString*methodName = [NSStringstringWithFormat:@"set%@%@:",[keysubstringToIndex:1].uppercaseString,[keysubstringFromIndex:1]];

SELsetter =sel_registerName(methodName.UTF8String);

if([objcrespondsToSelector:setter]) {

((void(*) (id,SEL,id))objc_msgSend) (objc,setter,value);

}

free(attributeList);

}

returnobjc;

}

//模型转字典

-(NSDictionary*)keyValuesWithObject{

unsignedintoutCount =0;

objc_property_t*propertyList =class_copyPropertyList([selfclass], &outCount);

NSMutableDictionary*dict = [NSMutableDictionarydictionary];

for(inti =0; i < outCount; i ++) {

objc_property_tproperty = propertyList[i];

//生成getter方法,并用objc_msgSend调用

constchar*propertyName =property_getName(property);

SELgetter =sel_registerName(propertyName);

if([selfrespondsToSelector:getter]) {

idvalue = ((id(*) (id,SEL))objc_msgSend) (self,getter);

/*判断当前属性是不是Model*/

if([valueisKindOfClass:[selfclass]] && value) {

value = [valuekeyValuesWithObject];

}

/**********************/

if(value) {

NSString*key = [NSStringstringWithUTF8String:propertyName];

[dictsetObject:valueforKey:key];

}

}

}

free(propertyList);

returndict;

}

3.写分类 比如给原有的类  加个属性或者加个方法

#import

staticconstvoid*associatedKey ="associatedKey";

staticconstvoid*topassociatedKey ="topassociatedKey";

staticconstvoid*letfassociatedKey ="letassociatedKey";

staticconstvoid*BottleassociatedKey ="BottleassociatedKey";

staticconstvoid*rightassociatedKey ="rightassociatedKey";

@implementationUIButton (ClickBlock)

-(void)setedgeWithTop:(CGFloat)topFloat andletf:(CGFloat)letfFloat andBottle:(CGFloat)bottleFloat andright:(CGFloat)right{

objc_setAssociatedObject(self, &topassociatedKey, [NSNumbernumberWithFloat:topFloat],OBJC_ASSOCIATION_COPY_NONATOMIC);

objc_setAssociatedObject(self, &letfassociatedKey, [NSNumbernumberWithFloat:letfFloat],OBJC_ASSOCIATION_COPY_NONATOMIC);

objc_setAssociatedObject(self, &BottleassociatedKey, [NSNumbernumberWithFloat:bottleFloat],OBJC_ASSOCIATION_COPY_NONATOMIC);

objc_setAssociatedObject(self, &rightassociatedKey, [NSNumbernumberWithFloat:right],OBJC_ASSOCIATION_COPY_NONATOMIC);

}

-(CGRect)edgerect{

NSNumber*topNumber =objc_getAssociatedObject(self, &topassociatedKey);

NSNumber*leftNumber =objc_getAssociatedObject(self, &letfassociatedKey);

NSNumber*bottleNumber =objc_getAssociatedObject(self, &BottleassociatedKey);

NSNumber*rightNumber =objc_getAssociatedObject(self, &rightassociatedKey);

if(topNumber && leftNumber && bottleNumber && rightNumber) {

returnCGRectMake(self.bounds.origin.x- leftNumber.floatValue,self.bounds.origin.y- topNumber.floatValue,self.bounds.size.width+ leftNumber.floatValue+rightNumber.floatValue,self.bounds.size.height+ topNumber.floatValue+bottleNumber.floatValue);

}else{

returnself.bounds;

}

}

//Category中的属性,只会生成setter和getter方法,不会生成成员变量

-(void)setClick:(clickBlock)click{

objc_setAssociatedObject(self,associatedKey, click,OBJC_ASSOCIATION_COPY_NONATOMIC);

[selfremoveTarget:selfaction:@selector(buttonClick)forControlEvents:UIControlEventTouchUpInside];

if(click) {

[selfaddTarget:selfaction:@selector(buttonClick)forControlEvents:UIControlEventTouchUpInside];

}

}

-(UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event{

CGRectrect = [selfedgerect];

if(CGRectEqualToRect(rect,self.bounds)) {

return[superhitTest:pointwithEvent:event];

}else{

returnCGRectContainsPoint(rect, point)?self:nil;

}

}

-(clickBlock)click{

returnobjc_getAssociatedObject(self,associatedKey);

}

-(void)buttonClick{

if(self.click) {

self.click();

}

}

4.动态方法解析


-(void)jump{

NSLog(@"monkey can not fly, but! monkey can jump");

}

+(BOOL)resolveInstanceMethod:(SEL)sel{

/*

如果当前对象调用了一个不存在的方法

Runtime会调用resolveInstanceMethod:来进行动态方法解析

我们需要用class_addMethod函数完成向特定类添加特定方法实现的操作

返回NO,则进入下一步forwardingTargetForSelector:

*/

#if0

returnNO;

#else

class_addMethod(self, sel,class_getMethodImplementation(self,sel_registerName("jump")),"v@:");

return[superresolveInstanceMethod:sel];

#endif

}

-(id)forwardingTargetForSelector:(SEL)aSelector{

/*

在消息转发机制执行前,Runtime系统会再给我们一次重定向的机会

通过重载forwardingTargetForSelector:方法来替换消息的接受者为其他对象

返回nil则进步下一步forwardInvocation:

*/

#if0

returnnil;

#else

return[[Birdalloc]init];

#endif

}

-(NSMethodSignature*)methodSignatureForSelector:(SEL)aSelector{

/*

获取方法签名进入下一步,进行消息转发

*/

return[NSMethodSignaturesignatureWithObjCTypes:"v@:"];

}

-(void)forwardInvocation:(NSInvocation*)anInvocation{

/*

消息转发

*/

return[anInvocationinvokeWithTarget:[[Birdalloc]init]];

}

你可能感兴趣的:(runtime的应用(仅供参考))