由于种种原因,简书等第三方平台博客不再保证能够同步更新,欢迎移步 GitHub:https://github.com/kingcos/Perspective/。谢谢!
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。
override func viewDidLoad() {
super.viewDidLoad()
demoButton.addTarget(self,
action: #selector(demoFunc),
for: .touchUpInside)
}
func demoFunc() {
// do something...
}
#selector()
据考证,#selector()
是 Swift 2.2 中新增的写法。使得选择方法更加安全,因为 IDE 可以自动提示自动补全,即可在编译时刻检查。
#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
网友评论