@selector
是Objective-C
时代的一个关键字
,它可以将一个方法转换并赋值给一个SEL 类型,它的表现很类似一个动态的函数指针
。在Objective-C 中selector 非常常用,从设定 target-action
,到自举询问是否响应
某个方法,再到指定接受通知时需要调用
的方法等等,都是有selector
来负责的。在Objective-C 里生成一个selector
的方法一般是这样的:
- (void)callMe {
// ...
}
- (void)callMeWithParam:(id)obj {
// ...
}
SEL someMetohd = @selector(callMe);
SEL anotherMethod = @selector(callMeWithParam:);
// 也可以使用NSSelectorFromString
SEL someMetohd = NSSelectorFromString(@"callMe");
SEL anotherMethod = NSSelectorFromString(@"callMeWithParam:");
一般为了方便,很多人会选择使用@selector
,但是如果要追求灵活
的话,可能会更愿意使用NSSelectorFromString
的版本----因为我们可以在运行时动态生成字符串,从而通过方法的名字来调用对应的方法。
在Swift 中没有@selector
了,我们要生成一个selector 的话可以使用字符串。当然方法必须被@objc 关键字
修饰,如果没有@objc
修饰,则无法正常被调用,也可以使用#selector 关键字
进行获取。Swift 里对应原来SEL 的类型是一个叫作Selector
的结构体
,它提供了一个接受字符串的初始化方法。上面的两个例子在Swift 中等效的写法是:
@objc func callMe() {
// ...
print("aaaaaaaa")
}
@objc func callMeWithParam(obj: AnyObject) {
// ...
print(obj)
}
let someMethod = Selector.init("callMe")
let anotherMethod = Selector.init("callMeWithParamWithObj:")
print(someMethod)
print(anotherMethod)
和Objective-C 中一样,但需要注意多参数方法名
的拼写
,即第一个参数,需要多加一个With 以及参数名
,之后的参数不需要添加,如果参数被 _
修饰时,则都无需拼写With 及参数名
:
@objc func callMeWithParam(_ obj: AnyObject, obj2: AnyObject) {
// ...
print(obj)
}
// 上面的方法为
let anotherMethod = Selector.init("callMeWithParam:obj2:")
// 修改方法参数
@objc func callMeWithParam(_ obj: AnyObject, _ obj2: AnyObject) {
// ...
print(obj)
}
// 上面的方法为
let anotherMethod = Selector.init("callMeWithParam::")
另外,如果方法的第一个
参数有外部变量
的话,需要使用外部变量,并且在第一个
外部变量之前
加上With
,其他
的外部变量则使用外部变量
:
@objc func callMeWithParam(external paramName: AnyObject) {
// ...
print(paramName)
}
// 上面的方法为
let anotherMethod = Selector.init("callMeWithParamWithExternal:")
// 修改方法参数
@objc func callMeWithParam(external paramName: AnyObject, exter param: AnyObject) {
// ...
print(paramName)
}
// 上面的方法为
let anotherMethod = Selector.init("callMeWithParamWithExternal:exter:")
其实最简单的方法就是使用#selector
关键字进行获取Selector
:
let method = #selector(self.callMeWithParam(external:exter:))
// 或者
let method = #selector(callMeWithParam(external:exter:))