iOS:在 Swift 中重新创建 addTarget() 的最佳实践?
iOS: Best practice for recreating addTarget() in Swift?
我正在创建一个自定义 UIControl
子类,并想添加一个 addTarget()
功能,类似于 UIButton。我该如何正确地做到这一点?到目前为止我有这个(它有效,但不确定是否是一个好的解决方案):
import UIKit
class RichLabel: UIControl {
var labelTarget: Any?
var labelAction: Selector?
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func addTarget(_ target: Any?, action: Selector) {
self.labelTarget = target
self.labelAction = action
}
func buttonAction() {
if let labelTarget = labelTarget, let labelAction = labelAction {
let _ = (labelTarget as AnyObject).perform(labelAction, with: self)
}
}
目标是从另一个视图添加的,像这样:
var richLabel: RichLabel {
let label = RichLabel()
label.setAttributedText(title: string)
label.addTarget(self, action: #selector(richLabelAction(label:)))
return label
}
由于 UIControl
已经允许您访问 func addTarget(_ target: Any?, action: Selector, for controlEvents: UIControlEvents)
,您可以直接使用它。例如,如果您将标签添加到 UIViewController
,并希望 viewController 能够对 editingDidBegin
之类的内容做出反应,您可以将此代码添加到 viewController :
@IBOutletWeak var richLabel: RichLabel!
override func viewDidLoad() {
super.viewDidLoad()
self.richLabel.addTarget(self, action: #selector(labelEditingDidBegin(_:)), for: UIControlEvents.editingDidBegin)
}
@objc func labelEditingDidBegin(_ sender: RichLabel) {
print(sender.text)
}
我不确定你的 RichLabel
是否允许编辑等,但你可以观察你需要的任何 UIControlEvent
,对此做出反应,然后在你的 [=] 中执行你需要的任何代码17=]函数。
如果您继承自 UIControl
,则无需对 addTarget
执行任何操作。调用者将在您的自定义 UIControl 上使用 addTarget
,就像他们使用任何其他控件一样。您的自定义控件所要做的就是决定何时调用这些操作,然后调用 sendActions(for:)
.
如果您的目标是让这个 RichLabel
class 功能像按钮一样,我会向它添加一个 UITapGestureRecognizer
,并在手势识别器中调用 self.sendActions(for: .touchUpInside)
.
class RichLabel: UIControl {
override init(frame: CGRect) {
super.init(frame: frame)
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(labelTapped))
addGestureRecognizer(tapGesture)
}
required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@objc func labelTapped() {
// When this happens, any object that called `addTarget`
// for the .touchUpInside event will get its callback triggered
sendActions(for: .touchUpInside)
}
}
我正在创建一个自定义 UIControl
子类,并想添加一个 addTarget()
功能,类似于 UIButton。我该如何正确地做到这一点?到目前为止我有这个(它有效,但不确定是否是一个好的解决方案):
import UIKit
class RichLabel: UIControl {
var labelTarget: Any?
var labelAction: Selector?
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func addTarget(_ target: Any?, action: Selector) {
self.labelTarget = target
self.labelAction = action
}
func buttonAction() {
if let labelTarget = labelTarget, let labelAction = labelAction {
let _ = (labelTarget as AnyObject).perform(labelAction, with: self)
}
}
目标是从另一个视图添加的,像这样:
var richLabel: RichLabel {
let label = RichLabel()
label.setAttributedText(title: string)
label.addTarget(self, action: #selector(richLabelAction(label:)))
return label
}
由于 UIControl
已经允许您访问 func addTarget(_ target: Any?, action: Selector, for controlEvents: UIControlEvents)
,您可以直接使用它。例如,如果您将标签添加到 UIViewController
,并希望 viewController 能够对 editingDidBegin
之类的内容做出反应,您可以将此代码添加到 viewController :
@IBOutletWeak var richLabel: RichLabel!
override func viewDidLoad() {
super.viewDidLoad()
self.richLabel.addTarget(self, action: #selector(labelEditingDidBegin(_:)), for: UIControlEvents.editingDidBegin)
}
@objc func labelEditingDidBegin(_ sender: RichLabel) {
print(sender.text)
}
我不确定你的 RichLabel
是否允许编辑等,但你可以观察你需要的任何 UIControlEvent
,对此做出反应,然后在你的 [=] 中执行你需要的任何代码17=]函数。
如果您继承自 UIControl
,则无需对 addTarget
执行任何操作。调用者将在您的自定义 UIControl 上使用 addTarget
,就像他们使用任何其他控件一样。您的自定义控件所要做的就是决定何时调用这些操作,然后调用 sendActions(for:)
.
如果您的目标是让这个 RichLabel
class 功能像按钮一样,我会向它添加一个 UITapGestureRecognizer
,并在手势识别器中调用 self.sendActions(for: .touchUpInside)
.
class RichLabel: UIControl {
override init(frame: CGRect) {
super.init(frame: frame)
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(labelTapped))
addGestureRecognizer(tapGesture)
}
required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@objc func labelTapped() {
// When this happens, any object that called `addTarget`
// for the .touchUpInside event will get its callback triggered
sendActions(for: .touchUpInside)
}
}