can not call selector and gesture delegate iOS 13.2 - swift

my code works in iOS 12 last version but after iOS 13 this code can't call the selector
I used UIGestureRecognizerDelegate for iOS 13
here is my code
let panGest = UIPanGestureRecognizer(target: self, action: #selector(self.handleTap(_:)))
panGest.delegate = self
txtVw.addGestureRecognizer(panGest)
here is my let txtVw = subVws as! UITextView , txtVw = subVws as! UITextView
I used this code:
let panGest = UIPanGestureRecognizer(target: self, action: #selector(self.handleTap(_:)))
self.view.addGestureRecognizer(panGest)
its work but I have one subview and for subview isn't work & call !!
isn't call self.handleTap or gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:)

Is this what you want?
class ViewController: UIViewController, UIGestureRecognizerDelegate {
#IBOutlet weak var textView: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
let gestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(handlePan))
gestureRecognizer.delegate = self
textView.addGestureRecognizer(gestureRecognizer)
textView.isUserInteractionEnabled = true
textView.isMultipleTouchEnabled = true
}
#objc func handlePan(_ gestureRecognizer: UIPanGestureRecognizer) {
if gestureRecognizer.state == .began || gestureRecognizer.state == .changed {
let translation = gestureRecognizer.translation(in: self.view)
//make sure the view is not nil
gestureRecognizer.view!.center = CGPoint(x: gestureRecognizer.view!.center.x + translation.x, y: gestureRecognizer.view!.center.y + translation.y)
gestureRecognizer.setTranslation(CGPoint.zero, in: self.view)
}
}
}

Related

use tag to combine #objc func methods

My code declares 2 different #objc func methods using UIPan gestureRecongnizzer. I would think there would be a way to use just 1 objc func method using a tag. All the function currently does is move the imageview around. I dont know if tag is the best way and I am open to other solutions I just want 1 func. Specifically look at pgGestureMethod and sgGestureMethod.
var pg = UIImageView()
var pgGesture = UIPanGestureRecognizer()
var pgCon = [NSLayoutConstraint]()
var sg = UIImageView()
var sgGesture = UIPanGestureRecognizer()
var sgCon = [NSLayoutConstraint]()
override func viewDidLoad() {
super.viewDidLoad()
[pg,sg].forEach({
$0.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview($0)
$0.isUserInteractionEnabled = true
})
pgGesture = UIPanGestureRecognizer(target: self, action: #selector(ViewController.pgGestureMethod(_:)))
pg.addGestureRecognizer(pgGesture)
sgGesture = UIPanGestureRecognizer(target: self, action: #selector(ViewController.sgGestureMethod(_:)))
sg.addGestureRecognizer(sgGesture)
}
#objc func pgGestureMethod(_ sender: UIPanGestureRecognizer){
self.view.bringSubviewToFront(pg)
let tranistioon = sender.translation(in: self.view)
pg.center = CGPoint(x: pg.center.x + tranistioon.x, y: pg.center.y + tranistioon.y)
sender.setTranslation(CGPoint.zero,in: self.view)
}
#objc func sgGestureMethod(_ sender: UIPanGestureRecognizer){
let tranistioon = sender.translation(in: self.view)
sg.center = CGPoint(x: sg.center.x + tranistioon.x, y: sg.center.y + tranistioon.y)
sender.setTranslation(CGPoint.zero,in: self.view)
}
Gesture recognisers have a view property that refers to the view to which they are added, so you don't even need a tag!
Just use one single action method like this:
#objc func pgGestureMethod(_ sender: UIPanGestureRecognizer){
// I replaced every "pg" with "sender.view!"
self.view.bringSubviewToFront(sender.view!)
let tranistioon = sender.translation(in: self.view)
sender.view!.center = CGPoint(x: sender.view!.center.x + tranistioon.x, y: sender.view!.center.y + tranistioon.y)
sender.setTranslation(CGPoint.zero,in: self.view)
}
If not writing self.view.bringSubviewToFront(sg) is actually intentional, you can simply check sender.view!:
#objc func pgGestureMethod(_ sender: UIPanGestureRecognizer){
if sender.view == pg {
self.view.bringSubviewToFront(pg)
}
let tranistioon = sender.translation(in: self.view)
sender.view!.center = CGPoint(x: sender.view!.center.x + tranistioon.x, y: sender.view!.center.y + tranistioon.y)
sender.setTranslation(CGPoint.zero,in: self.view)
}
welcome to the Stackoverflow.
So in your case, you can understand which gesture was called from parameter in gesture function.
class SomeViewController: UIViewController {
var pg = UIImageView()
var pgGesture = UIPanGestureRecognizer()
var pgCon = [NSLayoutConstraint]()
var sg = UIImageView()
var sgGesture = UIPanGestureRecognizer()
var sgCon = [NSLayoutConstraint]()
override func viewDidLoad() {
super.viewDidLoad()
[pg,sg].forEach {[unowned self] in
$0.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview($0)
$0.isUserInteractionEnabled = true
}
pgGesture = UIPanGestureRecognizer(target: self, action: #selector(gestureDidRecognize(_:)))
pg.addGestureRecognizer(pgGesture)
sgGesture = UIPanGestureRecognizer(target: self, action: #selector(gestureDidRecognize(_:)))
sg.addGestureRecognizer(sgGesture)
}
}
#objc private extension SomeViewController {
func gestureDidRecognize(_ gesture: UIPanGestureRecognizer){
guard let gestureView = gesture.view else { return }
let transition = gesture.translation(in: view)
switch gesture {
case pgGesture:
view.bringSubviewToFront(pg)
default: break
}
gestureView.center = CGPoint(
x: gestureView.center.x + transition.x,
y: gestureView.center.y + transition.y)
gesture.setTranslation(.zero, in: view)
}
}

UIImageView transform loses swipe gesture

I have an image that I want to rotate every time the user swipes on it. It works the first time, and first time only! How is it that the view is losing the swipe gesture recognizer?
myCircle = UIImageView( ... )
myCircle.isUserInteractionEnabled = true
let swipeLeft = UISwipeGestureRecognizer(target: self, action: #selector(swiping(sender:)))
swipeLeft.direction = .left
myCircle.addGestureRecognizer(swipeLeft)
let swipeRight = UISwipeGestureRecognizer(target: self, action: #selector(swiping(sender:)))
swipeRight.direction = .right
myCircle.addGestureRecognizer(swipeRight)
}
#objc func swiping(sender: UISwipeGestureRecognizer) {
// this function only called the first time!
if sender.direction == UISwipeGestureRecognizer.Direction.left {
myCircleRotation -= CGFloat(Double.pi/2)
} else if sender.direction == UISwipeGestureRecognizer.Direction.right {
myCircleRotation += CGFloat(Double.pi/2)
}
// if I comment out this next line, function is called (correctly) every swipe!
myCircle.transform = CGAffineTransform(rotationAngle: myCircleRotation)
}
You can add a UIView as a container view to your hierarchy, and then add the UIGestureRecognizers to the container view instead of to the UIImageView. This would allow your image to be rotated without impact to the gestures.
import UIKit
class ImageViewController: UIViewController {
#IBOutlet weak var myCircleView: UIImageView!
#IBOutlet weak var containerView: UIView!
var myCircleRotation:CGFloat = 0
override func viewDidLoad() {
super.viewDidLoad()
setupImage()
}
private func setupImage() {
let image = UIImage(named: "your-image")
myCircleView.image = image
myCircleView.isUserInteractionEnabled = true
let swipeLeft = UISwipeGestureRecognizer(target: self, action: #selector(swiping(sender:)))
swipeLeft.direction = .left
containerView.addGestureRecognizer(swipeLeft)
let swipeRight = UISwipeGestureRecognizer(target: self, action: #selector(swiping(sender:)))
swipeRight.direction = .right
containerView.addGestureRecognizer(swipeRight)
}
#objc func swiping(sender: UISwipeGestureRecognizer) {
// this function only called the first time!
if sender.direction == UISwipeGestureRecognizer.Direction.left {
myCircleRotation -= CGFloat(Double.pi/2)
} else if sender.direction == UISwipeGestureRecognizer.Direction.right {
myCircleRotation += CGFloat(Double.pi/2)
}
UIView.animate(withDuration: 0.5) {
self.myCircleView.transform = CGAffineTransform(rotationAngle: self.myCircleRotation)
}
}
}

unrecognized selector sent to instance

I suppose this question could be easily classed as a duplicate but can't find answer after searching.
inside cellForRowAt for my tableView
let chooseProfilePhotoPicker = ChooseProfilePhotoPicker(rootVC: self)
chooseProfilePhotoPicker.cropVC.delegate = self
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(chooseProfilePhotoPicker.iconImageViewTapped(_:)))
cell.iconImageView.addGestureRecognizer(tapGesture)
And the ChooseProfilePhotoPicker class:
class ChooseProfilePhotoPicker: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
var rootController: UIViewController
init(rootController: UIViewController) {
self.rootController = rootController
}
func iconImageViewTapped(_ recognizer: UITapGestureRecognizer) {
var pickerController = UIImagePickerController()
pickerController.delegate = self
pickerController.sourceType = UIImagePickerControllerSourceType.photoLibrary
rootController.present(myPickerController!, animated: true, completion: nil)
}
}
app crashes when I tap the iconImageView
If the action is supposed to run in in the instance of ChooseProfilePhotoPicker you have to set the target accordingly:
let tapGesture = UITapGestureRecognizer(target: chooseProfilePhotoPicker, action: #selector(chooseProfilePhotoPicker.iconImageViewTapped(_:)))

how to realize iOS swift playgrounds virtual keyboard feature .

Swift playground on iOS is good IDE for new programmers , and apple provide a virtual keyboard for programming , we can swipe the single button to input multi characters ,including “, ; : / “ …. , I want to realize the feature in my programme . How to implement this functionality? Using UIGestureRecognizerDelegate ? pan ? how to realized the animation that appeared in button when swipping ?
here is my code:
import UIKit
class myViewController: UIViewController, UIGestureRecognizerDelegate {
#IBOutlet weak var mybutton1: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let gestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(buttonPressed(_:)))
let moveRecognizer = UISwipeGestureRecognizer(target: self, action: #selector(moved(_:)))
let panRecognizer = UIPanGestureRecognizer(target: self, action: #selector(pan(_:)))
let longgestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(longLabelPressed(_:)))
longgestureRecognizer.minimumPressDuration = 1 //.001
mybutton1.isUserInteractionEnabled = true;
mybutton1.addGestureRecognizer(gestureRecognizer)
mybutton1.addGestureRecognizer(moveRecognizer)
mybutton1.addGestureRecognizer(panRecognizer)
mybutton1.addGestureRecognizer(longgestureRecognizer)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func moved(_ recognizer:UILongPressGestureRecognizer){
print("moved !!!!")
}
func pan(_ recognizer:UILongPressGestureRecognizer){
print("pan !!!!")
}
func longLabelPressed(_ recognizer:UILongPressGestureRecognizer){
// if let label = recognizer.view as? UIButton {
if recognizer.state == .began {
//label.textColor = UIColor.red
print("longlabelPressed begin !")
}
if recognizer.state == .ended {
//label.textColor = UIColor.black
print("longlabelPressed end !")
}
}
func buttonPressed(_ recognizer:UITapGestureRecognizer) {
print("labelPressed !")
}
}
//=============

remove UIGestures when leaving scene

I am having problems with my UIGestures in my game
At the gamescene, they work perfect, but when I move to another scene the UIgestures keep active and if I use them(swipe) than it crashes.
I know I have to use willmovefromview method in Gamescene file but have been working 2 days on this and still not working..
here is my viewcontroller file: (see comments for the gesture functions and gesture recognizers)
import UIKit
import SpriteKit
import AVFoundation
class GameViewController: UIViewController, UITextFieldDelegate{
//gesture functions
func swipedRight(sender: UISwipeGestureRecognizer){
let skView = view as SKView
let gameScene = skView.scene as GameScene
gameScene.swipedRight1(sender)
}
func swipedLeft(sender: UISwipeGestureRecognizer){
let skView = view as SKView
let gameScene = skView.scene as GameScene
gameScene.swipedLeft1(sender)
}
func swipedDown(sender: UISwipeGestureRecognizer){
let skView = view as SKView
let gameScene = skView.scene as GameScene
gameScene.swipedDown1(sender)
}
func swipedUp(sender: UISwipeGestureRecognizer){
let skView = view as SKView
let gameScene = skView.scene as GameScene
gameScene.swipedUp1(sender)
}
override func viewDidLoad() {
super.viewDidLoad()
let skView = view as SKView
skView.multipleTouchEnabled = false
scene = GameMenuScene(size: skView.bounds.size)
//scene.scaleMode = SKSceneScaleMode.ResizeFill
skView.showsFPS = true
skView.showsNodeCount = true
skView.presentScene(scene)
//Gesture recognizers
let swipeRight:UISwipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action: Selector("swipedRight:"))
swipeRight.direction = .Right
view.addGestureRecognizer(swipeRight)
let swipeLeft:UISwipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action: Selector("swipedLeft:"))
swipeLeft.direction = .Left
view.addGestureRecognizer(swipeLeft)
let swipeUp:UISwipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action: Selector("swipedUp:"))
swipeUp.direction = .Up
view.addGestureRecognizer(swipeUp)
let swipeDown:UISwipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action: Selector("swipedDown:"))
swipeDown.direction = .Down
view.addGestureRecognizer(swipeDown)
}
override func viewDidLayoutSubviews() {
}
override func prefersStatusBarHidden() -> Bool {
return true
}
}
PS: My app is starting on a menuscene, and the swipes must only be active at the gamescene, so I think I have to use didmovetoview method as well.
and here are the didmovetoview method and willmovefromview method on my gamescene file:
override func didMoveToView(view: SKView) {
}
override func willMoveFromView(view: SKView) {
}
Who is going to help me?
Thanks in advance
override func willMoveFromView(view: SKView) {
for recognizer in self.view.gestureRecognizers! {
self.view.removeGestureRecognizer(recognizer)
}
}
self.view.gestureRecognizers=nil;
It works for me.