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]];

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 5,875评论 0 9
  • 转载:http://yulingtianxia.com/blog/2014/11/05/objective-c-r...
    F麦子阅读 4,123评论 0 2
  • 本文转载自:http://yulingtianxia.com/blog/2014/11/05/objective-...
    ant_flex阅读 4,177评论 0 1
  • 图片发自简书App 1、 鹿鹿最近有点感情困惑,让我写写她的故事。 鹿鹿,今年28岁,前几个月刚升了副班长一职。其...
    维多and利亚阅读 4,044评论 6 8
  • 《岭南纪事》 俊友自美方 万里约鹏城 山顶观阔海 月明会佳朋 觥筹忆往昔 谈笑如风生 吾辈且为乐 正道修仁成 白云...
    赛德传播阅读 2,372评论 0 0

友情链接更多精彩内容