设为首页 加入收藏

TOP

Objective C运行时(runtime)技术的几个要点总结(二)
2015-01-22 20:57:24 来源: 作者: 【 】 浏览:29
Tags:Objective 行时 runtime 技术 要点 总结
复制代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 代码示例一: 1 @implementation CA 3 void dynamicMethodIMP(id self, SEL _cmd) 5 { 7 printf("SEL %s did not exist\n",sel_getName(_cmd)); 9 } 10 11 + (BOOL) resolveInstanceMethod:(SEL)aSEL 13 { 15 if (aSEL == @selector(t)) 17 { 19 class_addMethod([selfclass], aSEL, (IMP) dynamicMethodIMP, "v@:"); 21 return YES; 23 } 25 return [superresolveInstanceMethod:aSEL]; 27 } 28 29 @end 测试代码: CA * ca = [CA new] [ca performSelector:@selector(t)];
复制代码

  

执行结果

SEL t did not exist

复制代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 示例代码二: @implementation CA void dynamicMethodIMP(id self, SEL _cmd) { printf("SEL %s did not exist\n",sel_getName(_cmd)); } + (BOOL) resolveInstanceMethod:(SEL)aSEL { return YES; } - (id)forwardingTargetForSelector:(SEL)aSelector { if (aSelector == @selector(uppercaseString)) { return @"hello world"; } } 测试代码 : a = [[CA alloc]init]; NSLog(@"%@",[a performSelector:@selector(uppercaseString)];
复制代码

  

该测试代码的输出为:HELLO WORLD

对于该测试代码,由于a没有uppercaseString函数,因此会触发resolveInstanceMethod,但是由于该函数并没有添加selector,因此运行时发现找不到该函数,会触发

forwardingTargetForSelector函数,在forwardingTargetForSelector函数中,返回了一个NSString "hello world",因此会由该string来执行uppercaseString函数,最终返回大写的hello world。

复制代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 示例代码三: @implementation CA + (BOOL) resolveInstanceMethod:(SEL)aSEL { return YES; } - (id)forwardingTargetForSelector:(SEL)aSelector { return nil; }  测试代码: 1 a = [[CA alloc]init]; 2 NSLog(@"%@",[a performSelector:@selector(uppercaseString)];

  

复制代码

  

这段代码的执行顺序为:

(1):首先在程序刚执行,AppDelegate都还没有出来时,resolveInstanceMethod就被触发,

\

(2)等测试代码执行时,forwardingTargetForSelector被调用

\

(3)由于forwardingTargetForSelector返回了nil,因此运行时还是找不到uppercaseString selector,这时又会触发resolveInstanceMethod,由于还是没有加入selector,于是会crash。

\

(4) 使用class_copyPropertyList及property_getName获取类的属性列表及每个属性的名称

复制代码
u_int count; objc_property_t* properties= class_copyPropertyList([UIView class], &count); for (int i = 0; i < count ; i++) { const char* propertyName = property_getName(properties[i]); NSString *strName = [NSString stringWithCString:propertyName encoding:NSUTF8StringEncoding]; NSLog(@"%@",strName); }
复制代码

 以上代码获取了UIView的所有属性并打印属性名称, 输出结果为:

复制代码
skipsSubviewEnumeration viewTraversalMark viewDelegate monitorsSubtree backgroundColorSystemColorName gesturesEnabled deliversTouchesForGesturesToSuperview userInteractionEnabled tag layer _boundsWidthVariable _boundsHeightVariable _minXVariable _minYVariable _internalConstraints _dependentConstraints _constraintsExceptingSubviewAutoresizingConstraints _shouldArchiveUIAppearanceTags
复制代码

(5) 使用class_copyMethodList获取类的所有方法列表

获取到的数据是一个Method数组,Method数据结构中包含了函数的名称、参数、返回值等信息,以下代码以获取名称为例:

复制代码
u_int count; Method* methods= class_copyMethodList([UIView class], &count); for (int i = 0; i < count ; i++) { SEL name = method_getName(methods[i]); NSString *strName = [NSString stringWithCString:sel_getName(name) encoding:NSUTF8StringEncoding]; NSLog(@"%@",strName); }
复制代码

  代码执行后将输出UIView所有函数的名称,具体结果略。

其他一些相关函数:

1.SEL method_getName(Method m) 由Method得到SEL
2.IMP method_getImplementation(Method m)  由Method得到IMP函数指针
3.const char *method_getTypeEncoding(Method m)  由Method得到类型编码信息
4.unsigned int method_getNumberOfArguments(Method m)获取参数个数
5.char *method_copyReturnType(Method m)  得到返回值类型名称
6.IMP method_setImplem
首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇Objective-C调用Swift 下一篇Objective-C内存管理之引用计数

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: