其實這篇文章是對上一篇文章的補充(『iOS 概念性解說』一篇文章搞懂 Block 和 Delegate),因為SEL也是對于代碼的傳入,不同的是,Block 和 Delegate是代碼的傳入,SEL是方法的傳入,Block 和 Delegate可以做回調(diào),而SEL是用來做觸發(fā)的,為什么后面會講到。
SEL
聲明
SEL s1 = @selector(test);
SEL s2 = NSSelectorFromString(@"test");
名字
NSString *str = NSStringFromSelector(@selector(test));
執(zhí)行
[self performSelector:s1 ];
[self performSelector:@selector(test) ];
//帶有參數(shù)的
[test performSelector:@selector(test2:) withObject:@"param"];
判斷
[self respondsToSelector:s1]
整體
上面介紹了基本語法,在這里需要整體來看一下。
我們可以建立一個Test類
Test.h
@interface Test : NSObject
//無參數(shù)的方法
- (void)test1;
//有參數(shù)的方法
- (void)test2:(NSString *)str;
// 觸發(fā)
- (void)perform:(SEL)aSelector with:(NSObject*) object;
@end
Test.m
#import "Test.h"
@implementation Test
- (void)test1
{
NSLog(@"無參數(shù)");
}
- (void)test2:(NSString *)str
{
NSLog(@"有參數(shù)%@",str);
}
- (void)perform:(SEL)aSelector with:(NSObject*) object{
if ([object respondsToSelector:aSelector]) {
[object performSelector:aSelector];
}
}
@end
有了這個類,我們可以調(diào)用一下試試看了:
#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可以執(zhí)行該類中的SEL,要注意該類需要是NSObject的子類,因為performSelector是NSObject中的方法。
在執(zhí)行SEL前,我們需要確認該類中是否含有這個方法,可以使用respondsToSelector進行判斷,這樣更加安全一下,然后再執(zhí)行。
上述代碼中testEnter這個方法是傳入Test類中執(zhí)行的,我們通過[test perform:@selector(testEnter) with:self];傳入到Test類中,我們執(zhí)行了:
- (void)perform:(SEL)aSelector with:(NSObject*) object{
if ([object respondsToSelector:aSelector]) {
[object performSelector:aSelector];
}
}
UIButtion的點擊事件就是這樣實現(xiàn)的。
可能有人會問,為什么SEL不能做為回調(diào),這是由于SEL的執(zhí)行是需要他的類調(diào)用performSelector,也就是我們需要將類傳遞進來,如果有參數(shù),還需要傳遞上下文參數(shù),這樣做會增大程序的耦合性,一般不這么做。
那為什么觸發(fā)可以?以UIButtion為例,我們把方法傳入UIButtion,同時UIButtion本身也需要當前的ViewController。這是我們都傳遞進去是沒有問題的,即便點擊事件的方法需要傳入自己作為參數(shù)也是可以的,因為這段代碼本身就是在button中執(zhí)行的,不用withObject,直接self即可。
總結(jié)
結(jié)合之前的文章,綜上所述,根據(jù)不同情況,使用合理的方式傳入代碼,能夠提高程序的可讀性和可維護度。
有疑問的朋友歡迎給我留言指正,或者關(guān)注我的公眾號留言: