Search code examples
iosswiftuiimageview

Why doesn't hitTest(_:with:) interact with programmatically added UIImageView


I'm having trouble getting hitTest(_:with:) to traverse a UIImageView when it's added programmatically.

In IB I make a square area and give it a tag of 1. Within that square I insert a UIImageView (tag=2) (orange/white in screenshot below). In the ViewController I programmatically create another square(tag=3). Then add a UIImageView(tag=4) within that (red/green in screenshot below). The following picture shows this:

IB and programmatic embedded UIImageViews

I'm using touchesBegan(_:with:) to perform hitTest. When I touch the orange I get a printout of a view with tag 1 (expected). If I touch the white square I get printout with tag 2 (expected). These were created in IB.

When I touch the red square I get tag 3 (expected). When I touch green I get tag 3! (NOT expected). I've looked at the runtime hierarchy and don't see any difference in structure between IB & programmatic. It appears that hitTest(_:with:) doesn't recognize/traverse/include/detect the programmatic UIImageView. What's the difference?

Here's my ViewController code:

import UIKit

class ViewController: UIViewController {

  @IBOutlet var gameView: UIView!
  @IBOutlet var boardView: UIImageView!

  var g2 : UIView!
  var b2 : UIImageView!

  override func viewDidLoad() {
    super.viewDidLoad()

    g2 = UIView(frame: CGRect(x: 100, y: 50, width: 240, height: 240))
    g2.backgroundColor = .red
    g2.tag = 3
    view.addSubview(g2)

    b2 = UIImageView(frame: CGRect(x: 75, y: 75, width: 80, height: 80))
    b2.backgroundColor = .green
    b2.tag = 4
    g2.addSubview(b2)
  }

  override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    if event!.type != .touches { return }

    if let first = touches.first {
      let loc = first.location(in: view)
      if let v = view.hitTest(loc, with: nil) {
        print("\(v)")
      }
    }
  }

}

I've changed the programmatic UIImageView to a UIView and that IS detected by hitTest as expected.


Solution

  • UIImageView has isUserInteractionEnabled set to false by default, e.g. it doesn't receive any touches.

    This should be true for a storyboard too, probably you have enabled User Interactions Enabled checkmark.

    Most of other views have this property set to true by default, but if you wanna interact with UIImageView touches, you need to enable it explicitly.

    b2.isUserInteractionEnabled = true