SuperCodeBrah
SuperCodeBrah

Reputation: 3134

UITapGestureRecognizer not working - Swift 3

I see that there are a ton of these questions, and I think I'm following the accepted Swift 3 methodology, but I'm still getting nothing. I can see that the UITapGestureRecognizer has been attached. Here's my code:

let tileClick = UITapGestureRecognizer(target: self, action: #selector(GameManagement.initiateTileClick(_:)))
newView.addGestureRecognizer(tileClick)
newView.isUserInteractionEnabled = true

func initiateTileClick(_ sender: UITapGestureRecognizer) {
    print("initiate tile click")
}

A few things to note:

1) The view that I'm attaching the gesture recognizer to has a two views and a label within it that each cover the entire frame of the view, however, I tried attaching the recognizer to the label, which is the topmost child item and it still doesn't work.

2) Both the function that adds the recognizer and the function that is called on the tap are contained in an NSObject file. I have a variety of interconnected functions that I want to be able to call from multiple view controllers and would prefer to keep this in the separate NSObject file. The process worked when I had everything in a UIViewController file and stopped working when I moved the functions to the NSObject file.

3) I've tried changing GameManagement.initiateTileClick to self.initiateTileClick or just initiateTileClick and none of those worked.

Upvotes: 2

Views: 8530

Answers (3)

OmniBug
OmniBug

Reputation: 892

Obviously,this function is instance method.

func initiateTileClick(_ sender: UITapGestureRecognizer) {
    print("initiate tile click")
}

-

UITapGestureRecognizer(target: self, action:#selector(GameManagement.initiateTileClick(_:)))

but thisGameManagement.initiateTileClick(_:) looks like a class is calling a class method!The target should be the caller of method.self can't call GameManagement.initiateTileClick(_:).

Upvotes: 0

Rahul
Rahul

Reputation: 2100

If you are putting your views inside NSObject subclass then these views will lose their behaviors for UIResponder which manages the UI interactions as I am not able to see how you are adding these views to interface.

As you said, it was working inside ViewController because it manages view hierarchy and responder chain.

The solution would be to write extensions to separate code or better abstractions.

extension YourViewController {

   newView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(GameManagement.initiateTileClick(_:))))
   newView.isUserInteractionEnabled = true

   func initiateTileClick(_ sender: UITapGestureRecognizer) {
      print("initiate tile click")
   }
}

Upvotes: 7

Akhil Nair
Akhil Nair

Reputation: 444

Giving you an idea how the tap recogniser works.

Firstly add Tap gesture recogniser to your view controller. You have to put the object here as shown in the image.

Drop your tap gesture object here

Then control+drag the tap gesture object to your view and select delegate.

Then control+drag the recogniser to your swift file and action will be like this.

@IBAction func tapGesture(_ sender: UITapGestureRecognizer) {

}

Now you must have seen when you give some input to a text field, the keyboard appears. But if you press outside the text field, that is anywhere in the view, the keyboard hides. This is because of the tap gesture recogniser.

Consider you have a text field such that if you click in that text field, keyboard is appeared. But when you tap outside the textfield, the keyboard must hide.

Add this delegate

UITextFieldDelegate

Implement this:

@IBOutlet var phoneText: UITextField!

override func viewDidLoad() {

    super.viewDidLoad()

    // Do any additional setup after loading the view.

    exampleText.delegate = self
}

@IBAction func tapGesture(_ sender: UITapGestureRecognizer) {

    exampleText.endEditing(true)
}

Upvotes: 2

Related Questions