几个常用的回调方法

respondsToSelector与performSelector

这两个方法的优点是:
1. 与obj-c代码兼容性好。
2. 具有延迟执行特性。
3. 轻量级的回调机制。
缺点:
1. 回调产生的返回值只能为id类型,int等类型会产生错误。
2. 参数最多只能传入两个,但可以通过建立包含多个参数的类进行回避。同时返回值限制也可通过此方式解决,即建立一个输入类和一个输出类。
3. 即使在头文件里未声明该方法,也可以被调用到。

【示例1】利用respondsToSelector判断类是否实现了某方法:

Balloon.m

#import "Balloon.h"

@implementation Balloon

-(void) changeColor:(NSString *)color
{
    NSLog(@"My favorite color is %@",color);
}

@end

ViewController.m

- (void)viewDidLoad
{
    Balloon *balloon = [[Balloon alloc] init];
    
    SEL changeColorFun = @selector(changeColor:);
    
    if([balloon respondsToSelector:changeColorFun])
    {
        #pragma clang diagnostic pushs
        #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
        [balloon performSelector:changeColorFun withObject:@"blue"];
        #pragma clang diagnostic pop
    }
    
    [super viewDidLoad];
}

respondsToSelector还有一个类似的方法instancesRespondToSelector,它用来判断类是否包含某方法或属性,可以用该方法判断iOS系统的版本是否支持某个方法或者属性。上面的判断语句也可以改成:

if([Balloon instancesRespondToSelector:changeColorFun])

 

【示例2】通过performSelector延迟数秒后执行某一方法:

Balloon.m

#import "Balloon.h"

@implementation Balloon

-(void) changeColor:(NSString *)color
{
    NSLog(@"My favorite color is %@",color);
}

@end

ViewController.m

- (void)viewDidLoad
{
    SEL myFun = NSSelectorFromString(@"changeColor:");
    
    Balloon *balloon = [[Balloon alloc] init];

    #pragma clang diagnostic push
    #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
    [balloon performSelector:myFun withObject:@"green" afterDelay:5];
    #pragma clang diagnostic pop    
    
    [super viewDidLoad];
} 

objc_msgSend

在Objective-C中,消息是直到运行的时候才和方法实现绑定的。编译器会把一个消息表达式转换成一个对消息函数objc_msgSend的调用。该函数有两个主要参数:消息接收者和消息对应的方法名字。

objc_msgSend(receiver, selector)

同时接收消息中的任意数目的参数:

objc_msgSend(receiver, selector, arg1, arg2, …)

通过导入#import <objc/message.h>获得运行时的消息调用。其定义为:

id objc_msgSend(id theReceiver, SEL theSelector, …)

优点:
1. 轻量级的回调机制。
2. 无传入参数限制。
3. 相比performSelector,使用自动引数特征时,不产生警告。
4. 同系列的方法支持double、struct等类型的返回值,但仍然不支持int类型返回值(可使用NSNumber包装以回避)。

缺点:
1. 传入不符合约定的消息时,产生副作用继续运行,而非报错。

【示例3】

User.m

#import "User.h"

@implementation User

-(NSString *) baseInfo:(NSString *)name from:(NSString *)city
{    
    return [NSString stringWithFormat:@"My name is %@,I come from %@",name,city];
}

@end

ViewController.m

#import "ViewController.h"
#import <objc/message.h>
#import "User.h"

@implementation ViewController

- (void)viewDidLoad
{
    User *user = [[User alloc] init];
    SEL myFun = NSSelectorFromString(@"baseInfo:from:");
    NSString *strReturn = objc_msgSend(user, myFun,@"tom",@"beijing");
    NSLog(@"return value is :%@",strReturn);
    
    [super viewDidLoad];
}

转载于:https://www.cnblogs.com/CoderWayne/p/3410711.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值