Patrick
Patrick

Reputation: 312

How to add touch event for custom UIControl and determine the touched item in swift 5

I have created a custom UIControl. The UIControl contains multiple items like drawings and labels.

I want to be able to catch a tap on a label inside the ViewController. Note that I add components inside the UIControl and that I am not using NIB/XIB files).

I am rather new at swift/iOS development. I am working in XCode 10.3 and swift 5. I did some Google searches which did not help me much. I also found this reference (How to add touch event for custom uicontrol and controller?), but I could not get that to work either.

I have added a minimal code example (based on a new project).

\\ 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")
//        }
    }
}

The Main.storyboard looks like this:

Main.storyboard

(https://postimg.cc/V5h7fdFf)

I would like to be able to implement the changeLabel() function in the ViewController.swift. Or implement something similar in functionality, such that it "catches" the tap on the UILabel and knows which UILabel was tapped.

Upvotes: 2

Views: 1566

Answers (1)

Blazej SLEBODA
Blazej SLEBODA

Reputation: 9925

First of all, all interactions with UILabel are disabled by default. To change it, set isUserInteractionEnabled to 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?" }
        }
    }

In Storyboard add a Tap Gesture Recognizer and set its "Sent Actions" to "changeLabel", "Referencing outlet collections" to your custom SomeUI IBOutlet referenced here by "sui" property

@IBOutlet weak var sui: SomeUI!

Upvotes: 2

Related Questions