| 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