IOS动态方法决议

首先,笔者想通过下面一段代码来解释什么是动态方法决议,动态方法决议能做什么。

@interface AA : NSObject
- (void)out;
- (void)say:(NSString*)say;
@end
 
@implementation AA
- (void)out
{
  NSLog(@"Out");
}
int main (int argc, const char * argv[]) 
{ 
    @autoreleasepool {
        AA * aa = [[AA alloc] init]; 
        [aa out];
        [aa say:@”Hello”]; 
        [foo release]; 
    } 
    return 0; 
}

以上代码执行后会产生什么样的结果?我想大家都应该很清楚,那就是程序会crash,因为我们并未实现方法say:,在AA方法的method list中和它的父类method list中都找不到其相应实现,所以会crash

而我们今天的主题就是为了解决这样的问题,动态决议可以让我们实现动态地为类添加方法以避免未实现的方法调用。

 

动态方法决议

 

Object-C为我们提供了名为动态决议的手段,可以使我们在运行时动态地为一个selector添加实现。我们只要实现 +resolveInstanceMethod: 和/或 +resolveClassMethod: 方法,并在其中为指定的 selector  提供实现即可(通过调用运行时函数 class_addMethod 来添加)。这两个方法都是 NSObject 中的类方法,其原型为:

+ (BOOL)resolveClassMethod:(SEL)name; 
+ (BOOL)resolveInstanceMethod:(SEL)name;

参数name表示动态决议的selector,返回值根据官方文档的说法,它的作用表示动态决议是否成功。

 

然后我们将代码修正如下:

void function(id self,SEL _cmd,NSString * saySomething)
{
  NSLog(@"动态添加方法:%@",saySomething);
}
@interface AA : NSObject
- (void)out;
- (void)say:(NSString*)say;
@end
@implementation AA
- (void)out
{
  NSLog(@"Out");
}
+ (BOOL)resolveInstanceMethod:(SEL)name
{
  NSLog(@"resolveInstanceMethod called %@",NSStringFromSelector(name));
  if(name==@selector(say:)){
     class_addMethod([self class], name, (IMP)function, "v@:@");
     return YES;
  }
  return [super resolveInstanceMethod:name];
}
+ (BOOL)resolveClassMethod:(SEL)sel
{
  NSLog(@"resolveClassMethod called %@",NSStringFromSelector(sel));
  return [super resolveClassMethod:sel];
}
@end


程序将会正常运行,并输出:

Out

resolveInstanceMethod called say:

动态添加方法:Hello

 

从以上代码中我们可以看到,除了比较关键的resolveInstanceMethod外还有一个重要的函数为class_addMethod,它能在运行期动态地为 name 这个 selector 添加实现:funcyion。class_addMethod 是运行时函数,所以需要导入头文件:objc/runtime.h。

其函数原型如下:

BOOL class_addMethod(Class cls,SEL name,IMP imp,const char* types);

调用 方法如下:

class_addMethod([self class], name, (IMP)function, "v@:@");

我们都知道每一个object-C方法的本质其实就是一个至少带有两个参数(self,_cmd)的普通C函数,因此在这个例子中笔者定义了一个say函数,从外部调用看,它只包含了一个NSString类型参数

在class_addMethod的4个参数中唯一让笔者一开始不太明白和是第四个参数,types,,查阅资料后得知其是一个定义该函数返回值类型和参数类型的字符串

本例中types参数为"i@:@“,按顺序分别表示:

v      : v表示返回值为void

@    :参数id(self)

:       :SEL(_cmd)对象

@    :id(str)

 

一句话来说,type表明了该函数从左到右返回值及参数的类型,@表示object对象。:表示selector对象

其他类型如下:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值