小窥 iOS 中的 Target-Action 设计模式

2017-01-14 10:21:23来源:http://www.jianshu.com/p/b00056fac0a8作者:萌面大道人点击

Design Pattern in iOS


Info:
macOS 10.12.1
Xcode 8.2 Beta 1
Swift 3.0

前言

在前两天学习 iOS 中的 UISlider 控件时,看到官方文档提到,Slider 使用了 Target-Action 设计模式。即当用户移动滑块,将通知应用。同理,UIButton 也使用了该设计模式。那么,我们能从这个设计模式中学到什么呢?


Target-Action

Target-Action,意为 目标-行为,行为即要调用的方法,目标即消息的接收对象(Objective-C 语言使用消息机制,类似但不同于方法调用,该两种概念可能未来会进行探讨)。整个过程为:用户点击按钮,触发某事件发生,该消息由按钮传到另外的接收对象,接收对象再做相应处理。接收对象可以为任何对象,但通常为控制器(Controller)。


Responder Chain

在有关于 Target-Action 的官方文档章节中,提到了通过设置 Target 为 nil 来使用响应链。这样可以使得在运行时(Runtime)决定 Target 对象。关于此的探讨可以参照 Dominik Hauser 的 Utilize The Responder Chain For Target-Action 一文。


但是鉴于个人能力有限,而且在其原文中,作者新加了这么一句话:



Utilize The Responder Chain For Target-Action

显然,作者虽然了解响应链的存在,但不会去使用。


Demo
Interface Builder

通过 Interface Builder 可以拖线来实现(注意 Connection 选择 Action)。



Action

之后便可以在其内部进行其他操作。


@IBAction func buttonClick(_ sender: Any) {
// do something...
}

当然,也可以先定义方法,再拖线,这样也是允许的。


Code

通过代码进行绑定 Target,可以先采用将控件拖线至代码中,这时 Connection 选择 Outlet。纯代码可以无视拖线。



Outlet

之后便可以通过 addTarget(_:action:for:) 来绑定 Target 和 Action。



addTarget(_:action:for:)
override func viewDidLoad() {
super.viewDidLoad()
demoButton.addTarget(self,
action: #selector(demoFunc),
for: .touchUpInside)
}
func demoFunc() {
// do something...
}

#selector()

据考证,#selector() 是 Swift 2.2 中新增的写法。使得选择方法更加安全,因为 IDE 可以自动提示自动补全,即可在编译时刻检查。



Selector 结构体

#selector() 在 Swift 中为 Selector 结构体类型,但其本质是 Objective-C 的运行时概念。如果有方法为 private,则需要在方法前加上 @objc 才能运行正常。


override func viewDidLoad() {
super.viewDidLoad()
let selectorStruct = #selector(demoFunc)
demoButton.addTarget(self,
action: selectorStruct,
for: .touchUpInside)
}
@objc private func demoFunc() {
// do something...
}

关于 Selector 也可以参考喵神的文章,所有本文提及的文章均在参考资料中列出。


参考资料

Target-Action
Target-Action
Utilize The Responder Chain For Target-Action
在 Target-Action 中使用响应链
SELECTOR




最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台