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)
    }

}