首先我们来看一下下面这个方法:
func addTarget(_ target: Any?, action: Selector, for controlEvents: UIControlEvents)
其中的Selector 源自 Objective-C,例如 SEL 类型,以及 @selector() 方法选择器。由于Swift语法体系不含有消息机制,所以这里只能借助Cocoa Framework本身的消息机制来了。而Swift中所引入的Select()也是为了迎合action这里的selector,Swift 中也兼容了这个概念。
Selector结构体
先来看一下Selector的源码:
public struct Selector : ExpressibleByStringLiteral {
/// Create a selector from a string.
public init(_ str: String)
/// Create an instance initialized to `value`.
public init(unicodeScalarLiteral value: String)
/// Construct a selector from `value`.
public init(extendedGraphemeClusterLiteral value: String)
/// Create an instance initialized to `value`.
public init(stringLiteral value: String)
}
extension Selector : Equatable, Hashable {
/// The hash value.
///
/// **Axiom:** `x == y` implies `x.hashValue == y.hashValue`
///
/// - Note: the hash value is not guaranteed to be stable across
/// different invocations of the same program. Do not persist the
/// hash value across program runs.
public var hashValue: Int { get }
}
extension Selector : CustomStringConvertible {
/// A textual representation of `self`.
public var description: String { get }
}
extension Selector : CustomReflectable {
/// Returns a mirror that reflects `self`.
public var customMirror: Mirror { get }
}
从中可以看出selector其实是一个结构体。它实现了字面量的协议,可以使用字符串直接定义selector。
Selector的几种初始化方法
#第一种
aButton.addTarget(self,
action: Selector("aButtonClick"),
for: .touchUpInside)
#第二种
bButton.addTarget(self,
action: #selector(bButtonClick),
for: .touchUpInside)
若是 Swift 中的私有方法,则必须赋予其 Objective-C 的 runtime(运行时)。即在方法名前加上 @objc
:
@IBOutlet weak var wgButton: UIButton!
@IBOutlet weak var anotherWgButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
wgButton.addTarget(self,
action: #selector(wgButtonClick),
for: .touchUpInside)
}
@objc func wgButtonClick(_ button: UIButton) {
let btnLabel = button.titleLabel?.text ?? "nil"
print(btnLabel)
print(#function)
}