In my project I have tap gesture with following setup
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(sceneViewTapped(gesture:)))
tapGesture.cancelsTouchesInView = true
tapGesture.delaysTouchesBegan = true
self.view.addGestureRecognizer(tapGesture)
And also has Touch method like override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?)
I have setup touch gesture with tapGesture.delaysTouchesBegan = true to work both gesture as well as Touch delegate methods
It is working fine till iOS12, But in iOS13 Touch delay has been increased so user must drag his finger and wait until drawing starts because touch method called delayed
Please refer below image , Sometime gesture lost , Delayed on starting of drawing.
If I remove delaysTouchesBegan it is smooth again.
Can anyone can help me to solve this ?
SAMPLE PROJECT
To quick test this stuff download raywenderlich project https://www.raywenderlich.com/5895-uikit-drawing-tutorial-how-to-make-a-simple-drawing-app
Add Following code in ViewController.swlft
override func viewDidLoad() {
super.viewDidLoad()
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(viewTapped(gesture:)))
tapGesture.delaysTouchesBegan = true
self.view.addGestureRecognizer(tapGesture)
}
#objc func viewTapped(gesture:UITapGestureRecognizer) {
print("View Tapped")
}
This was iOS 13.0 bug
After update to the iOS 13.1 Will fix this issue automatically
Hopefully helpful to someone :)
Related
I'm working on a small SpriteKit game for tvOS. I need to receive input when the user clicks the play/pause button on the remote. Looking at the docs, it appears that I should just have to add a UITapGestureRecognizer to my scene's view. I implemented the following code:
override func didMove(to view: SKView) {
let tapPlayPause = UITapGestureRecognizer(target: self, action: #selector(tapTesting))
tapPlayPause.allowedPressTypes = [NSNumber(value: UIPress.PressType.playPause.rawValue)]
view.addGestureRecognizer(tapPlayPause)
let swipeUp = UISwipeGestureRecognizer(target: self, action: #selector(swipeUp))
swipeUp.direction = .up
view.addGestureRecognizer(swipeUp)
}
#objc func tapTesting(_ sender: UITapGestureRecognizer) {
print("TAP")
}
However, when I run the app on my Apple TV 4K (running tvOS 15), there is no output and from what I can tell no tap code is getting triggered.
I have tried the code with self.isUserInteractionEnabled = true as well but I still do not receive tap inputs.
The swipe gesture I implemented above works perfectly thought, and the tap gesture works on my iOS devices. Does anyone have any idea as to why this is the case?
Thanks!
For tvOS gestures, you also need to set allowedTouchTypes to .indirect
tapPlayPause.allowedTouchTypes = [NSNumber(touchType: .indirect)]
I have been unable to make it work the gesture recognizer in my app.
Under viewDidLoad I added these
let orangeIndicatorTap = UITapGestureRecognizer(target: self, action: #selector(self.orangeIndicatorClick(_:)))
orangeIndicatorTap.numberOfTapsRequired = 1
orangeIndicatorTap.delegate = self
conceptMiddleOrangeIndicator.tag = 1
conceptMiddleOrangeIndicator.isUserInteractionEnabled = true
conceptMiddleOrangeIndicator.addGestureRecognizer(orangeIndicatorTap)
let greenIndicatorTap = UITapGestureRecognizer(target: self, action: #selector(self.greenIndicatorClick(_:)))
greenIndicatorTap.numberOfTapsRequired = 1
conceptMiddleGreenIndicator.isUserInteractionEnabled = true
conceptMiddleGreenIndicator.addGestureRecognizer(greenIndicatorTap)
let purpleIndicatorTap = UITapGestureRecognizer(target: self, action: #selector(self.purpleIndicatorClick(_:)))
greenIndicatorTap.numberOfTapsRequired = 1
conceptMiddlePurpleColorIndicator.isUserInteractionEnabled = true
conceptMiddlePurpleColorIndicator.addGestureRecognizer(purpleIndicatorTap)
Is there any other way i could add a click event to my overlapping custom uitextviews?
you can use touchesBegan to identify which view has been touched.
use this code hope this help.
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first
if touch.view == yourView_outlet {
// add your code here
} else if touch.view == yourView_outlet {
// add your code here
}
}
I fixed it, It was because of an overlay that wasnt being removed correctly.
It seems that, it visibly is removed but logically underlying overlay views were not removed. That's why the gesture doesnt work.
Hopefully this will help someone in the future.
I have a subclassed UIButton (DragButton) that I would like to be able to perform pan / pinch / rotate on. Instances of DragButton are created programmatically. There may be 1, there may be 20. All depends on the user.
I am experiencing issues in getting these subclassed buttons to properly work with gestures. The main issue is none of the gestures trigger! Within DragButton class, inside the awakeFromNib instance method, the gestures don't work at all. Inside layoutSubviews, the panning works properly the first drag, but each subsequent hold and drag increases the velocity of the movement a considerably amount. (Pinch and Rotate work properly in layoutSubviews though.) It's almost like layoutSubviews is 'doubling up' the gestures on each interaction. But awakeFromNib doesn't work at all. My guess here is the new buttons have not been unarchived yet.
Here is the code in DragButton
class DragButton: UIButton, UIGestureRecognizerDelegate {
override func awakeFromNib() {
let panRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.draggedView(_:)))
let pinchRecognizer = UIPinchGestureRecognizer(target: self, action: #selector(self.pinchedView(_:)))
let rotateRecognizer = UIRotationGestureRecognizer(target: self, action: #selector(self.rotatedView(_:)))
panRecognizer.delegate = self
pinchRecognizer.delegate = self
rotateRecognizer.delegate = self
self.isUserInteractionEnabled = true
self.isMultipleTouchEnabled = true
self.addGestureRecognizer(panRecognizer)
self.addGestureRecognizer(pinchRecognizer)
self.addGestureRecognizer(rotateRecognizer)
}
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
superview?.bringSubview(toFront: self)
}
Also in DragButton are the methods for handling the gestures, however I don't think my problem lies in there.
So to recap - I need a subclassed button (DragButton) to be instantiated programmatically, and have it react to all the 3 gestures. The issue with my code above is none of the gestures work with awakeFromNib, however they work faulty with layoutSubviews on the first tap, then each subsequent tap doubles up the velocity of the panning (hence the fault).
I am looking for a simple solution in swift to add the ability to tap anywhere on screen and dismiss the keyboard. I read a lot of answers on here but they all throw errors for me. The one I have used before is this:
override func viewDidLoad() {
super.viewDidLoad()
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target:self, action: #selector(ViewController.dismissKeyboard))
view.addGestureRecognizer(tap)
This worked with one of my projects but it doesn't seem to work with any others. Whenever I try to add this to other projects I get error Type 'ViewController' has no member 'dismissKeyboard'.
You need to add a method above any reference to it. I put this code at the beginning of my files:
func dismissKeyboard() {
//Causes the view (or one of its embedded text fields) to resign the first responder status and drop into background
view.endEditing(true)
}
And then whenever I need to reference the .dismissKeyboard I use this inside the viewDidLoad():
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(LoginViewController.dismissKeyboard))
view.addGestureRecognizer(tap) // Allows dismissal of keyboard on tap anywhere on screen besides the keyboard itself
And make sure to replace 'LoginViewController' with the current View Controller. As per your example, that is just 'ViewController'
If you are looking for a more in depth answer, see this by 7KV7:
https://stackoverflow.com/a/5711504/6312593
You can try this one, its very simple solution, frequently used in swift to dismiss the keyboard.
Just add this function, that's it.
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?)
{
self.view.endEditing(true)
}
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: Selector("dismiss:"))
view.addGestureRecognizer(tap)
func dismiss(gest : UITapGestureRecognizer){
view.endEditing(true)
}
This is working fine, try it.
I'm building a game that is primarily played by tapping the screen (anywhere). I have currently added a settings button that when tapped, opens up a settings window.
Problem is, when the settings button is tapped, interaction happens in the game too. Is there any way to prevent this from happening?
My settings screen works in conjunction with a settings function and the override touches began function through a boolean expression.
The game is played through a UITapGestureRecognizer that was added to the view in didMoveToView.
/* Game Interaction & Playability */
override func didMoveToView(view: SKView) {
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: Selector("tapped:"))
view.addGestureRecognizer(tap)
}
/* Settings Button Interaction */
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches {
let positionInScene = touch.locationInNode(self)
let touchedNode = self.nodeAtPoint(positionInScene)
if let name = touchedNode.name {
if name == "Settings" {
if settingsOpen == false {
settings()
} else {
settings()
}
}
}
}
}
Well, you've got a couple gesture recognizers working here. You don't actually need to add a recognizer to the view to know if someone is tapping it. That's handled already for you (hence the reason why touchesBegan works without adding another recognizer).
I would say remove that extra recognizer, and move the code for tapped: to your touchesBegan.