swift GestureRecognizer in cells - swift

I would like to make long press tableview Cells, But i'm getting error:
UIGestureRecognizer.Type' does not have a member named 'state'
Here's the code
override func viewDidLoad() {
super.viewDidLoad()
var gesture: UILongPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: "longPressed:")
gesture.minimumPressDuration = 2.0
self.view.addGestureRecognizer(gesture)
}
func longpressed() {
if(UIGestureRecognizer.state == UIGestureRecognizerState.Ended){
print("ended")
} else if (UIGestureRecognizer.state == UIGestureRecognizerState.Began){
print("began")
}
}
And Yes I've created Bridging-Header.h and imported this file:
#import <UIKit/UIGestureRecognizerSubclass.h>
I want swift tutorial not objective-c!

Add a gesture recogniser to your UITableView like
var gestureRec = UILongPressGestureRecognizer(target: self, action: "didTap:")
self.tableView.addGestureRecognizer(gestureRec)
Implement a didTap function, which would look something like this.
func didTap(sender : UIGestureRecognizer)
{
if sender.state == .Began {
var location = sender.locationInView(self.tableView)
var indexPath = self.tableView.indexPathForRowAtPoint(location)
var cell = self.tableView.cellForRowAtIndexPath(indexPath!)
}
}
This should work.

Try this in your longPress method:
func longpressed(sender: UILongPressGestureRecognizer) {
var state = sender.state
if(state.state == UIGestureRecognizerState.Ended){
print("ended")
} else if (state.state == UIGestureRecognizerState.Began){
print("began")
}
}

Related

Tap gesture (gesture began) not recognised in Swift

UITapGestureRecogniser began state is not recognised, only ended is recognised.
override func viewDidLoad() {
let tapgr = UITapGestureRecognizer(target: self, action: #selector(tapTrigger(recongizer:)))
bottomBar.addGestureRecognizer(tapgr)
}
#objc func tapTrigger(recongizer: UITapGestureRecognizer){
if recongizer.state == .began{
print("recognised") // does not print
}else if recogniser.state == .ended{
print("ended") //prints
}
}
What I am trying to do is highlight a view(not the view the recogniser is added) when a touch is recognised and unhighlight when it is cancelled.
Instead of using UITapGestureRecognizer you can use UILongPressGestureRecognizer to get the different state.
Like this:
let tapgr = UILongPressGestureRecognizer(target: self, action: #selector(tapTrigger(recongizer:)))
tapgr.minimumPressDuration = 0
bottomBar.addGestureRecognizer(tapgr)
#objc func tapTrigger(recongizer: UITapGestureRecognizer){
if recongizer.state == .began{
print("recognised")
} else if recongizer.state == .ended{
print("ended") //prints
}
}

pass Data When Long Press in Table view Cell

there is a Table View to show phone contact . i want to send phone number and email to another View Controller when Long Pressed the Cell . Long Press Work Correctly But I cant Pass Data to another View Controller .
enter image description here
VC 1 :
override func viewDidLoad() {
super.viewDidLoad()
let longPress = UILongPressGestureRecognizer(target: self, action: #selector(longpress))
tbMain.addGestureRecognizer(longPress)
}
Long Press Method for table view cell :
#objc func longpress(sender: UILongPressGestureRecognizer) {
if sender.state == UIGestureRecognizer.State.began {
let touchPoint = sender.location(in: tbMain)
if tbMain.indexPathForRow(at: touchPoint) != nil {
let cell = tbMain.dequeueReusableCell(withIdentifier: "testCell") as! NewContactCell
print("Long press Pressed:)")
self.actionVC = self.storyboard!.instantiateViewController(withIdentifier: "ActionsViewController") as? ActionsViewController
UIView.transition(with: self.view, duration: 0.25, options: [.transitionCrossDissolve], animations: {
self.view.addSubview( self.actionVC.view)
}, completion: nil)
}
}
}
VC 2 :
internal var strPhoneNUmber : String!
internal var strEmail : String!
override func viewDidLoad() {
super.viewDidLoad()
print("Phone: \(strPhoneNUmber!)")
// Do any additional setup after loading the view.
}
Get phone number and email from cell object
self.actionVC.strPhoneNUmber = cell.strPhoneNUmber // get phone number from cell object
self.actionVC. strEmail = cell.strEmail // get email from cell object
code would be like
#objc func longpress(sender: UILongPressGestureRecognizer) {
if sender.state == UIGestureRecognizer.State.began {
let touchPoint = sender.location(in: tbMain)
if tbMain.indexPathForRow(at: touchPoint) != nil {
let cell = tbMain.dequeueReusableCell(withIdentifier: "testCell") as! NewContactCell
print("Long press Pressed:)")
self.actionVC = self.storyboard!.instantiateViewController(withIdentifier: "ActionsViewController") as? ActionsViewController
**self.actionVC.strPhoneNUmber = cell.strPhoneNUmber // get phone number from cell object
self.actionVC. strEmail = cell.strEmail // get email from cell object**
UIView.transition(with: self.view, duration: 0.25, options: [.transitionCrossDissolve], animations: {
self.view.addSubview( self.actionVC.view)
}, completion: nil)
}
}
}
I don't see when your trying to pass the data.. you have quite a few way to perform that action first you can use delegation to achieve passing the data
protocol YourDelegate : class {
func passData(phoneNumber: String, email: String)
}
weak var delegate: YourDelegate?
#objc func longpress(sender: UILongPressGestureRecognizer) {
if sender.state == UIGestureRecognizer.State.began {
let touchPoint = sender.location(in: tbMain)
if tbMain.indexPathForRow(at: touchPoint) != nil {
let cell = tbMain.dequeueReusableCell(withIdentifier: "testCell") as! NewContactCell
print("Long press Pressed:)")
self.actionVC = self.storyboard!.instantiateViewController(withIdentifier: "ActionsViewController") as? ActionsViewController
self.delegate = self
**delegate?.passData(cell.strPhoneNumber, cell.strEmail)**
UIView.transition(with: self.view, duration: 0.25, options: [.transitionCrossDissolve], animations: {
self.view.addSubview( self.actionVC.view)
}, completion: nil)
}
}
}
class ???: UIViewController, YourDelegate {
var strPhoneNUmber : String!
var strEmail : String!
override func viewDidLoad() {
super.viewDidLoad()
print("Phone: \(strPhoneNUmber!)")
// Do any additional setup after loading the view.
}
func passData(phoneNumber: String, email: String) {
handle...
}
}
its not clear to me if the actionVC is the one you want to pass the data to but if so you have an instance.. just set the properties but ill still recommend sticking with the delegation pattern
actionVC.strPhoneNumber = cell.strPhoneNumber
or use a segue
self.performSegue(withIdentifier: "yourIdentifier", sender: arr[indexPath.row])
use prepare for segue to create an instance to set his properties according to the sender..
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let destvc = segue.destination as? YourClass
destvc.phoneNumber = sender.phoneNumber as? String
destvc.email = sender.email as? String
}

Prevent UIButton Long Press Repeating Function

The following UILongPressGestureRecognizer code works, however it repeatedly runs the long() press function when the button is held. I'd like to have it only run one time while the user is pressing. Is this possible?
override func viewDidLoad() {
let tapGesture = UITapGestureRecognizer(target: self, action: #selector (tap))
let longGesture = UILongPressGestureRecognizer(target: self, action: #selector(long))
tapGesture.numberOfTapsRequired = 1
shiftBtn.addGestureRecognizer(tapGesture)
shiftBtn.addGestureRecognizer(longGesture)
}
#objc func tap() {
print("Short Tap")
}
#objc func long() {
print("Long press")
}
Thanks!
You should call the long When gesture activated. it's called one time whenever long gesture active.
#objc func hitlongprass(_ sender : Any){
guard let longPress = sender as? UILongPressGestureRecognizer else
{ return }
if longPress.state == .began { // When gesture activated
long()
}
else if longPress.state == .changed { // gesture Calls multiple times by time changed
}
else if longPress.state == .ended { // When gesture end
}
}
func long() {
print("Long press")
}
Calling:
let longGesture = UILongPressGestureRecognizer(target: self, action: #selector(hitlongprass(_:)))
You can check state of gesture in long function. Ex check state is begin long press

why is bringSubviewToFront() only working for panning, not tapping?

view.bringSubviewToFront(tappedView)
is working when I drag (pan) views but not when I tap them. My issue is that when I have one view layered over the other, I want the bottom view to come to the front when tapped. Currently it will only come to the front when dragged. Do I need some additional code to do this? Thanks.
Here's an excerpt from my code for more context:
#objc func didPan(_ recognizer: UIPanGestureRecognizer) {
let location = recognizer.location(in: self.view)
switch recognizer.state {
case .began:
currentTappedView = moviePieceView.filter { pieceView -> Bool in
let convertedLocation = view.convert(location, to: pieceView)
return pieceView.point(inside: convertedLocation, with: nil)
}.first
currentTargetView = movieTargetView.filter { $0.pieceView == currentTappedView }.first
case .changed:
guard let tappedView = currentTappedView else { return }
let translation = recognizer.translation(in: self.view)
tappedView.center = CGPoint(x: tappedView.center.x + translation.x, y: tappedView.center.y + translation.y)
recognizer.setTranslation(.zero, in: view)
view.bringSubviewToFront(tappedView)
```
I had this same problem, I managed to solve it this way:
Add a gestureRecognizer to your view and put this in your code. Don't forget to set the delegate as well when attaching this to the code!
#IBAction func tappedView1(recognizer: UITapGestureRecognizer) {
view.bringSubviewToFront(myView)
}
Put this in your viewDidLoad:
let tap = UITapGestureRecognizer(target: self, action: #selector(tappedView1))
tap.cancelsTouchesInView = false
self.view.addGestureRecognizer(tap)
If you want to do that from your panGesture check my question.
Thank you all. It worked when I wrote a second function in addition to didPan().
This is the additional code:
override func viewDidLoad() {
super.viewDidLoad()
configureLabel()
let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(didPan(_:)))
view.addGestureRecognizer(panGestureRecognizer)
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(didTap(_:)))
view.addGestureRecognizer(tapGestureRecognizer)
}
#objc func didTap(_ recognizer: UITapGestureRecognizer) {
let location = recognizer.location(in: self.view)
currentTappedView = moviePieceView.filter { pieceView -> Bool in
let convertedLocation = view.convert(location, to: pieceView)
return pieceView.point(inside: convertedLocation, with: nil)
}.first
guard let tappedView = currentTappedView else { return }
view.bringSubviewToFront(tappedView)
}
HOWEVER, I found out you can also just tick the "User Interaction Enabled" box in the Image View if you don't want to do it programmatically.

UITapGesture firing before previous one has ended

I've set up a tap gesture to complete an action like this:
func setupGestures() {
let singleTap = UITapGestureRecognizer(target: self, action: #selector(handleSingleTap))
singleTap.numberOfTapsRequired = 1
sceneView.addGestureRecognizer(singleTap)
}
#objc func handleSingleTap(_ sender: UITapGestureRecognizer) {
if sender.state == UIGestureRecognizerState.ended {
jumpUp()
}
}
func jumpUp() {
if let action = jumpAction {
addBlocks()
playerNode.runAction(action)
}
}
However, I can tap multiple times and my object stays in the air (continues the jump action) as it's registering the tap gesture continuously rather than letting it finish first before another tap can be registered. How can I fix this so that a tap gesture can only happen one at a time? Other answers suggested adding the sender.state == UIGestureRecognizerState.ended but it hasn't worked.
Fixed it by passing sender as an argument to the jumpUp() function and adding sender.isEnabled = true in its the completion handler:
#objc func handleSingleTap(_ sender: UITapGestureRecognizer) {
sender.isEnabled = false
jumpUp(sender)
}
func jumpUp(_ sender: UITapGestureRecognizer) {
if let action = jumpAction {
addBlocks()
playerNode.runAction(action, completionHandler: {
sender.isEnabled = true
})
}
}