Pan gesture recognizer selector won't work - ios

In a SpriteKit game, I am trying to create a UIPanGestureRecognizer without using Interface Builder, so in the didMoveToView method of my SKScene, I wrote this :
let panGestureRecogniser = UIPanGestureRecognizer(target: view, action: "didPan:")
view.addGestureRecognizer(panGestureRecogniser)
Still in my SKScene class, I wrote this function :
func didPan(sender:UIGestureRecognizer) {
println("Panned")
}
My issue is that when I run my app, and when I pan on the screen, this error in thrown :
2015-05-12 19:28:01.955 Game[7342:2394353] -[SKView didPan:]: unrecognized selector sent to instance 0x154520690
I don't understand what's wrong, I have tried to move the function in both my view controller and app delegate, but it doesn't seem to make any difference...

Change
let panGestureRecogniser = UIPanGestureRecognizer(target: view, action: "didPan:")
To
let panGestureRecogniser = UIPanGestureRecognizer(target: self, action: "didPan:")

Related

dismissKeyboard - unrecognized selector

In some View Controller I have the following commands:
//Looks for single or multiple taps.
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(LoginVC.dismissKeyboard))
//add tap gesture
view.addGestureRecognizer(tap)
but after changing language from swift3 to swift4 I have started receiving the following error
[iosapp_v147.ChangePasswordViewController dismissKeyboard]: unrecognized selector sent to instance 0x155e04090
Any help rendered will be greatly appreciated
The error message is indicating that the target object (a ChangePasswordViewController) receiving the dismissKeyboard call has no function declared as #objc dismissKeyboard()
Make sure that ChangePasswordViewController has a dismissKeyboard function declared with the #objc attribute. That's required for all #selector references.
You should also be able to declare the selector without the "LoginVC." prefix, since the your target is self.
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))
Finally, make sure the function signature has no labels (dismissKeyboard(this:that:)).
If it's none of those things, post the function declaration.

How do I listen to tap gestures on different controls in the same view?

I have two copies of a control (its called a RatingControl). How do I write handlers that can be invoked on the correct object when somebody double taps on them?
I have:
#IBOutlet weak var ratingControl: RatingControl!
#IBOutlet weak var ratingControl2: RatingControl!
inside a TableViewController and then
override func viewDidLoad() {
super.viewDidLoad()
let tapGR = UITapGestureRecognizer(target: ratingControl, action: #selector(RatingControl.doubleTap(_:)))
tapGR.numberOfTapsRequired = 2
self.view.addGestureRecognizer(tapGR)
let tapGR2 = UITapGestureRecognizer(target: ratingControl2, action: #selector(RatingControl.doubleTap(_:)))
tapGR2.numberOfTapsRequired = 2
self.view.addGestureRecognizer(tapGR2)
}
RatingControl.doubleTap(_) is an innocuous event handler.
When there is a double tap on the second rating control, the doubleTap method is called but is dispatched on the first rating control object!
I have tried setting two targets on a single UITapGestureRecognizer but it runs into the same problem.
Thanks much!
You need to add the gesture recognizers to the two rating controls instead of to self.view.
Try this:
let tapGR = UITapGestureRecognizer(target: self, action: #selector(RatingControl.doubleTap(_:)))
tapGR.numberOfTapsRequired = 2
ratingControl.addGestureRecognizer(tapGR) // ratingControl, not self.view
let tapGR2 = UITapGestureRecognizer(target: self, action: #selector(RatingControl.doubleTap(_:)))
tapGR2.numberOfTapsRequired = 2
ratingControl2.addGestureRecognizer(tapGR2) // ratingControl2, not self.view
There are 2 parts to hooking up a gesture recognizer: the target, which determines which object gets notified when the recognizer is triggered, and the view it's attached to, which determines from which view the recognizer recognizes the gesture.
You've got 2 gesture recognizes configured the same way, both attached to self.view. They are therefore going to respond to taps on self.view (which I assume is the view controller's content view.) I don't think it's clear which gesture recognizer is going to be triggered when you tap in that case.
You should have 2 different views and attach a different gesture recognizer to each one. If ratingControl1 and ratingControl2 are view objects, perhaps you meant to attach the gesture recognizers directly to them, rather than to self.view?

pick up all UIGestureRecognizer events in callback?

Is there a way to pickup all UIGestureRecognizer events in one method? (besides via directing all their selectors to the same method).
So for example:
// Add Gesture Recogniser (Long Press)
let longPressGR = UILongPressGestureRecognizer(target: self, action: #selector(GcMapView.longPressAction(_:)))
longPressGR.minimumPressDuration = 1
self.addGestureRecognizer(longPressGR)
// Add Gesture Recogniser (Pan)
let mapDragRecognizer = UIPanGestureRecognizer(target: self, action: #selector(GcMapView.panAction(_:)))
mapDragRecognizer.delegate = self
self.addGestureRecognizer(mapDragRecognizer)
// Add Gesture Recogniser (Pinch)
let pinchGestureRecogniser = UIPanGestureRecognizer(target: self, action: #selector(GcMapView.pinchAction(_:)))
pinchGestureRecogniser.delegate = self
self.addGestureRecognizer(pinchGestureRecogniser)
// SOME METHOD NOW TO PICKUP ALL EVENTS
func PICKUPALLEVENTS (sender:UIGestureRecognizer) {
print("(String(gestureRecognizer.dynamicType) - \(gestureRecognizer.state.hashValue) ")
}
No, I don't think there is any way to do that.
Have you tried adding a UIGestureRecognizer to your target, then checking the dynamic type of the UIGestureRecognizer in the selector called?

Swift: Getting target of UIPanGestureRecognizer

In my ViewController.swift, I have an array that contains custom UIViews. Every time one is created, I add a UIPanGestureRecognizer to it like this:
var panRecognizer = UIPanGestureRecognizer(target: self, action: "detectPan:")
newCard.gestureRecognizers = [panRecognizer]
This links to my detectPan(recognizer: UIPanGestureRecognizer) function, which handles movement. However, since I have multiple objects linked to the function, I'm not sure how I determine from which one the input is coming.
Is there anything like (the nonexistent) recognizer.target that I could use? Should I just handle the panning from within each of the custom UIViews instead?
Any help would be appreciated!
First of all, you should declare your panRecognizer with let.
let panRecognizer = UIPanGestureRecognizer(target: self, action: "detectPan:")
Second of all, you should not set the gestureRecognizers property of any UIView. This is bad practice because UIKit may have already added its own gesture recognizers to that view behind the scenes. If you subsequently remove those recognizers by assigning [panRecognizer] to that property, you may get unexpected behavior. To add your pan gesture recognizer, do this:
newCard.addGestureRecognizer(panRecognizer)
Then, in your detectPan(recognizer: UIPanGestureRecognizer) method you can detect which UIView was panned with the following code:
func detectPan(recognizer: UIPanGestureRecognizer) {
switch recognizer.view {
case self.customViewArray[0]:
// do something
case self.customViewArray[1]:
// do something else
case ... :
// ...
}

Using Gesture Recognizers

Before you respond, keep in mind I am very new to swift (last time I coded was 2 years ago and that was OBJC), and I seem to be having an error. Here's a sample of my code:
init(sourceView:UIView, menuItems:Array<String>) {
originView = sourceView
sideBarTableViewController.tableData = menuItems
animator = UIDynamicAnimator(referenceView: originView)
let showGestureRecognizer:UISwipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action: "handleSwipe:")
showGestureRecognizer.direction = UISwipeGestureRecognizerDirection.Right
originView.addGestureRecognizer(showGestureRecognizer)
let hideGestureRecognizer:UISwipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action: "handleSwipe:")
}
I seem to be having errors with the UISwipeGestureRecognizer target. I can't set it to self, because it gives me this error: 'self' used before super.init call.
Any help is very much appreciated.
I don't think it's linked to the gesture recognisers. Try to modify your Init() method, by adding at the beginning (inside):
super.init()
This will initialize the object with the parameters of the class you are overriding. Also it will probably ask you to add override before your init method.

Resources