/** * Adds a new method to a class with a given name and implementation. * * @param cls The class to which to add a method. * @param name A selector that specifies the name of the method being added. * @param imp A function which is the implementation of the new method. The function must take at least two arguments—self and _cmd. * @param types An array of characters that describe the types of the arguments to the method. * * @return YES if the method was added successfully, otherwise NO * (for example, the class already contains a method implementation with that name). * * @note class_addMethod will add an override of a superclass's implementation, * but will not replace an existing implementation in this class. * To change an existing implementation, use method_setImplementation. */ OBJC_EXPORT BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); |
参数解释:
Class cls:要添加新方法的类的class。 SEL name:要添加的方法名,可以任意取名,只要符合方法的命名规则。 IMP imp:IMP就是Implementation的缩写,它是指向一个方法实现的指针,每一个方法都有一个对应的IMP。这里需要的是IMP,通过OBJC_EXPORT IMP class_getMethodImplementation(Class cls, SEL name) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0)方法获取。 表示由编译器生成的、指向实现方法的指针。也就是说,这个指针指向的方法就是我们要添加的方法。 const char *types:参数的类型说明 如: “v@:”意思就是这已是一个void类型的方法,没有参数传入。 “i@:”就是说这是一个int类型的方法,没有参数传入。 “i@:@”就是说这是一个int类型的方法,有一个参数传入。 |
注意,用这种方式添加的方法是无法直接调用的,必须用performSelector:调用。因为你添加方法是在运行时添加的,你在编译的时候还没有这个本类方法,所以当然不行啦。而performSelector是运行时系统负责去找方法的,在编译时候不做任何校验;如果直接调用编译是会自动校验。
使用场景:
我们首先要明确 Objective-C 作为一种动态语言,它会将部分代码放置在运行时的过程中执行,而不是编译时,所以在执行代码时,不仅仅需要的是编译器,也同时需要一个运行时环境(Runtime),为了满足一些需求,苹果开源了 Runtime Source 并提供了开放的 api 供开发者使用。
1、当项目中,需要继承某一个类(subclass),但是父类中并没有提供我需要的调用方法,而我又不清楚父类中某些方法的具体实现;
2、需要为这个类写一个分类(category),在这个分类中,我可能需要替换/新增某个方法(注意:不推荐在分类中重写方法,而且也无法通过 super 来获取所谓父类的方法)。大致在这两种情况下,我们可以通过 class_addMethod 来实现我们想要的效果。
参考博文:
http://www.jianshu.com/p/6a3672b8be40
http://www.cnblogs.com/chipmuck/p/5807190.html