如何为自定义 UIControl 添加触摸事件并在 swift 5 中确定触摸的项目

Posted

技术标签:

【中文标题】如何为自定义 UIControl 添加触摸事件并在 swift 5 中确定触摸的项目【英文标题】:How to add touch event for custom UIControl and determine the touched item in swift 5 【发布时间】:2019-08-21 19:15:18 【问题描述】:

我创建了一个自定义 UIControl。 UIControl 包含多个项目,如绘图和标签。

我希望能够点击 ViewController 内的标签。 请注意,我在 UIControl 中添加了组件,并且我没有使用 NIB/XIB 文件)。

我在 swift/ios 开发方面比较陌生。我在 XCode 10.3 和 swift 5 中工作。我做了一些谷歌搜索,但对我没有多大帮助。我也找到了这个参考 (How to add touch event for custom uicontrol and controller?),但我也无法让它工作。

我添加了一个最小的代码示例(基于一个新项目)。

\\ File: SomeUI.swift
import UIKit

@IBDesignable
class SomeUI: UIControl 

    private var componentsAdded = false
    private let labelOne = UILabel()
    private let labelTwo = UILabel()

    override func draw(_ rect: CGRect) 
        if !componentsAdded 
            componentsAdded = true
            self.addSubview(labelOne)
            labelOne.text = "one"
            labelOne.sizeToFit()
            self.addSubview(labelTwo)
            labelTwo.text = "two"
            labelTwo.sizeToFit()
        
        labelOne.center = CGPoint(x: 10, y: 10)
        labelTwo.center = CGPoint(x: 10, y: 40)
    

\\ File: ViewController.swift
import UIKit

class ViewController: UIViewController 

    override func viewDidLoad() 
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    

    @IBOutlet weak var someLabel: UILabel!

    func changeLabel() 
//        switch sender 
//        case labelOne: someLabel.text = "one"
//        case labelOne: someLabel.text = "two"
//        default: println("other")
//        
    

Main.storyboard 如下所示:

(https://postimg.cc/V5h7fdFf)

我希望能够在 ViewController.swift 中实现changeLabel() 函数。或者在功能上实现类似的东西,例如它“捕捉” UILabel 上的点击并知道哪个 UILabel 被点击了。

【问题讨论】:

我在第二种情况选项中犯了一个错误。它应该是:// case labelTwo: someLabel.text = "two" 【参考方案1】:

首先,所有与 UILabel 的交互默认都是禁用的。要更改它,请将 isUserInteractionEnabled 设置为 true。

import UIKit

@IBDesignable
class SomeUI: UIControl 

    private var componentsAdded = false
    let labelOne = UILabel()
    private let labelTwo = UILabel()

    required init?(coder: NSCoder) 
        super.init(coder: coder)
        labelOne.isUserInteractionEnabled = true
    

    override func draw(_ rect: CGRect) 
        if !componentsAdded 
            componentsAdded = true
            self.addSubview(labelOne)
            labelOne.text = "one"
            labelOne.sizeToFit()
            self.addSubview(labelTwo)
            labelTwo.text = "two"
            labelTwo.sizeToFit()
        
        labelOne.center = CGPoint(x: 10, y: 10)
        labelTwo.center = CGPoint(x: 10, y: 40)
    




\\ File: ViewController.swift
    import UIKit

    class ViewController: UIViewController 

        override func viewDidLoad() 
            super.viewDidLoad()
            // Do any additional setup after loading the view.
        

        @IBOutlet weak var someLabel: UILabel!
        @IBOutlet weak var sui: SomeUI!

        @IBAction func changeLabel(_ gestureRecognizer: UITapGestureRecognizer) 
            let view = gestureRecognizer.view
            let loc = gestureRecognizer.location(in: view)
            let subview = sui.hitTest(loc, with: nil)

            switch subview 
            case sui.labelOne: print("1") someLabel.text = "label one tapped"
            case sui.labelTwo: print("2") someLabel.text = "label two tapped"
            default: print("0") someLabel.text = "TAPPIO?" 
        
    

在 Storyboard 中添加一个 Tap Gesture Recognizer 并将其“Sent Actions”设置为“changeLabel”、“Reference outlet collections”到您的自定义 SomeUI IBOutlet,此处由“sui”属性引用

@IBOutlet weak var sui: SomeUI!

【讨论】:

以上是关于如何为自定义 UIControl 添加触摸事件并在 swift 5 中确定触摸的项目的主要内容,如果未能解决你的问题,请参考以下文章

如何忽略触摸事件并将它们传递给另一个子视图的 UIControl 对象?

在自定义 UIControl 对象中定义自定义触摸区域

自定义 UIControl,动作调用两次

如何为分析添加 Firebase 自定义事件?

如何让自定义 UIControl 作为推送操作参与 segue?

UIControl