『iOS概念性解说』SEL详解

其实这篇文章是对上一篇文章的补充(『iOS 概念性解说』一篇文章搞懂 Block 和 Delegate),因为SEL也是对于代码的传入,不同的是,Block 和 Delegate是代码的传入,SEL是方法的传入,Block 和 Delegate可以做回调,而SEL是用来做触发的,为什么后面会讲到。


SEL

声明

SEL s1 = @selector(test);
SEL s2 = NSSelectorFromString(@"test");

名字

NSString *str = NSStringFromSelector(@selector(test));

执行

[self performSelector:s1 ];
[self performSelector:@selector(test) ];
//带有参数的
 [test performSelector:@selector(test2:) withObject:@"param"];

判断

[self respondsToSelector:s1]

整体

上面介绍了基本语法,在这里需要整体来看一下。
我们可以建立一个Test类
Test.h

@interface Test : NSObject
//无参数的方法
- (void)test1;
//有参数的方法
- (void)test2:(NSString *)str;
// 触发
- (void)perform:(SEL)aSelector with:(NSObject*) object;
@end

Test.m

#import "Test.h"

@implementation Test
- (void)test1
{
    NSLog(@"无参数");
}

- (void)test2:(NSString *)str
{
    NSLog(@"有参数%@",str);
}
- (void)perform:(SEL)aSelector with:(NSObject*) object{
    if ([object respondsToSelector:aSelector]) {
        [object performSelector:aSelector];
    }
}
@end

有了这个类,我们可以调用一下试试看了:

#import "ViewController.h"
#import "Test.h"
@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    SEL s1 = @selector(test);
    SEL s2 = NSSelectorFromString(@"test");
   NSString *str = NSStringFromSelector(@selector(test));
    NSLog(@"%@",str);
    Test *test = [Test new];
    [test performSelector:@selector(test1)];
    [test performSelector:@selector(test2:) withObject:@"param"];
    [self performSelector:s1 ];
    [self performSelector:s2 ];
    [self performSelector:@selector(test) ];
    if ([self respondsToSelector:s1]) {
        NSLog(@"含有test方法");
    }
    if ([self respondsToSelector:@selector(test1)]) {
        NSLog(@"含有test1方法");
    }else{
        NSLog(@"不含有test1方法");
    }
    [test perform:@selector(testEnter) with:self];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
- (void)test{
    NSLog(@"test");
}
- (void)testEnter{
    NSLog(@"test inter");
}
@end

运行上述代码,可以看出,对一个类使用performSelector可以执行该类中的SEL,要注意该类需要是NSObject的子类,因为performSelector是NSObject中的方法。
在执行SEL前,我们需要确认该类中是否含有这个方法,可以使用respondsToSelector进行判断,这样更加安全一下,然后再执行。
上述代码中testEnter这个方法是传入Test类中执行的,我们通过[test perform:@selector(testEnter) with:self];传入到Test类中,我们执行了:

- (void)perform:(SEL)aSelector with:(NSObject*) object{
    if ([object respondsToSelector:aSelector]) {
        [object performSelector:aSelector];
    }
}

UIButtion的点击事件就是这样实现的。
可能有人会问,为什么SEL不能做为回调,这是由于SEL的执行是需要他的类调用performSelector,也就是我们需要将类传递进来,如果有参数,还需要传递上下文参数,这样做会增大程序的耦合性,一般不这么做。
那为什么触发可以?以UIButtion为例,我们把方法传入UIButtion,同时UIButtion本身也需要当前的ViewController。这是我们都传递进去是没有问题的,即便点击事件的方法需要传入自己作为参数也是可以的,因为这段代码本身就是在button中执行的,不用withObject,直接self即可。

总结

结合之前的文章,综上所述,根据不同情况,使用合理的方式传入代码,能够提高程序的可读性和可维护度。
有疑问的朋友欢迎给我留言指正,或者关注我的公众号留言:


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • *面试心声:其实这些题本人都没怎么背,但是在上海 两周半 面了大约10家 收到差不多3个offer,总结起来就是把...
    Dove_iOS阅读 27,217评论 30 472
  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 1,788评论 0 9
  • 前言:面试笔试都是必考语法知识点。请认真复习和深入研究OC。 目录:iOS-面试题-OC基础篇 (1) - (84...
    麦穗0615阅读 4,276评论 0 33
  • 西安的天气总是阴晴不定,像小孩子的脾气,叫人难以琢磨。刚才还是艳阳高照,城墙下,吃过晚饭的市民都聚集于此,嬉闹玩乐...
    谈谈谈是谁阅读 154评论 0 1
  • 一个想要复辟的领导也好,老农民也罢,都是有血有肉的mankind。文字不在于辞藻华丽,这种小生活细情感更加感人肺腑...
    wynn木木阅读 187评论 0 0