Passing arguments to selector in Swift

mike picture mike · Apr 6, 2017 · Viewed 92.2k times · Source

I'm programmatically adding a UITapGestureRecognizer to one of my views:

let gesture = UITapGestureRecognizer(target: self, action: #selector(self.handleTap(modelObj:myModelObj)))

self.imageView.addGestureRecognizer(gesture)

func handleTap(modelObj: Model) {
  // Doing stuff with model object here
}

The first problem I encountered was "Argument of '#selector' does not refer to an '@Objc' method, property, or initializer.

Cool, so I added @objc to the handleTap signature:

@objc func handleTap(modelObj: Model) {
  // Doing stuff with model object here
}

Now I'm getting the error "Method cannot be marked @objc because the type of the parameter cannot be represented in Objective-C.

It's just an image of the map of a building, with some pin images indicating the location of points of interest. When the user taps one of these pins I'd like to know which point of interest they tapped, and I have a model object which describes these points of interest. I use this model object to give the pin image it's coordinates on the map so I thought it would have been easy for me to just send the object to the gesture handler.

Answer

Ashley Mills picture Ashley Mills · Apr 6, 2017

It looks like you're misunderstanding a couple of things.

When using target/action, the function signature has to have a certain form…

func doSomething(sender: Any)

or

func doSomething(sender: Any, forEvent event: UIEvent)

where…

The sender parameter is the control object sending the action message.

In your case, the sender is the UITapGestureRecognizer

Also, #selector() should contain the func signature, and does NOT include passed parameters. So for…

func handleTap(sender: UIGestureRecognizer) {

}

you should have…

let gesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(sender:)))

Assuming the func and the gesture are within a view controller, of which modelObj is a property / ivar, there's no need to pass it with the gesture recogniser, you can just refer to it in handleTap