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

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,335评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,895评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,766评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,918评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,042评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,169评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,219评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,976评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,393评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,711评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,876评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,562评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,193评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,903评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,142评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,699评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,764评论 2 351

推荐阅读更多精彩内容

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