how to add pan gesture on long pressing a button [duplicate] - swift

I want to trigger two action on button click and button long click. I have add a UIbutton in my interface builder. How can i trigger two action using IBAction can somebody tell me how to archive this ?
this is the code i have used for a button click
#IBAction func buttonPressed (sender: UIButton) {
....
}
can i use this method or do i have to use another method for long click ?

If you want to perform any action with single tap you and long press the you can add gestures into button this way:
#IBOutlet weak var btn: UIButton!
override func viewDidLoad() {
let tapGesture = UITapGestureRecognizer(target: self, #selector (tap)) //Tap function will call when user tap on button
let longGesture = UILongPressGestureRecognizer(target: self, #selector(long)) //Long function will call when user long press on button.
tapGesture.numberOfTapsRequired = 1
btn.addGestureRecognizer(tapGesture)
btn.addGestureRecognizer(longGesture)
}
#objc func tap() {
print("Tap happend")
}
#objc func long() {
print("Long press")
}
This way you can add multiple method for single button and you just need Outlet for that button for that..

#IBOutlet weak var countButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
addLongPressGesture()
}
#IBAction func countAction(_ sender: UIButton) {
print("Single Tap")
}
#objc func longPress(gesture: UILongPressGestureRecognizer) {
if gesture.state == UIGestureRecognizerState.began {
print("Long Press")
}
}
func addLongPressGesture(){
let longPress = UILongPressGestureRecognizer(target: self, action: #selector(longPress(gesture:)))
longPress.minimumPressDuration = 1.5
self.countButton.addGestureRecognizer(longPress)
}

Why not create a custom UIButton class, create a protocol and let the button send back the info to delegte. Something like this:
//create your button using a factory (it'll be easier of course)
//For example you could have a variable in the custom class to have a unique identifier, or just use the tag property)
func createButtonWithInfo(buttonInfo: [String: Any]) -> CustomUIButton {
let button = UIButton(type: .custom)
button.tapDelegate = self
/*
Add gesture recognizers to the button as well as any other info in the buttonInfo
*/
return button
}
func buttonDelegateReceivedTapGestureRecognizerFrom(button: CustomUIButton){
//Whatever you want to do
}

Related

How to pass a UIView on UIButton as a parameter on click event

I generated a multiple UIButton and UIView using loop, the problem is, I want that generated UIView to be hidden when the generated UIButton was clicked,
The question is, how can I pass the UIView on a UIButton click event so that the system knows what UIView will going to be hidden
This is my code that generate UIButtons and UIViews
for (key, value) in myStringsArray {
let myButton = UIButton()
let myView = UIView()
panelButton.tag = value
panelButton.addTarget(self, action: #selector(onMyButtonClick), for: .touchUpInside)
}
The only data that I can pass on .tag was Int
And this is my onMyButtonClick function that listen on click event of the UIButton
#objc func onMyButtonClick (sender: UIButton) {
print(sender.tag)
}
What I want to do is to have a click listener function that is working like this
func clickMe (view: UIView, isOpen: Bool) {
view.isHidden = isOpen
}
You can assign the button and the view the same tag.
then you can find the view by tag and hide it.
#objc func onMyButtonClick (sender: UIButton) {
print(sender.tag)
if let foundView = view.viewWithTag(sender.tag) {
foundView.isHidden = true
}
}

Views not performing segue

I have a collection of views and I want to make that when they are tapped, it will perform the same segue. and no view performs any segue.
class ViewController: UIViewController {
#IBOutlet var categoryViews: [UIView]!
let tapGesture = UIGestureRecognizer(target: self, action: #selector(ViewController.move(tap:)))
override func viewDidLoad() {
super.viewDidLoad()
for category in (0..<categoryViews.count) {
categoryViews[category].addGestureRecognizer(tapGesture)
categoryViews[category].isUserInteractionEnabled = true
}
// Do any additional setup after loading the view.
}
#objc func move(tap: UIGestureRecognizer) {
performSegue(withIdentifier: "Animals", sender: nil)
}
}
A single instance of UITapGestureRecognizer can be added to a single view.
In your code, since you're using a single instance of UITapGestureRecognizer for each view, the tapGesture will be added only to the last view in categoryViews array.
You need to create different UITapGestureRecognizer instance for each view in categoryViews, i.e.
class ViewController: UIViewController {
#IBOutlet var categoryViews: [UIView]!
override func viewDidLoad() {
super.viewDidLoad()
categoryViews.forEach {
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(move(tap:)))
$0.addGestureRecognizer(tapGesture)
$0.isUserInteractionEnabled = true
}
}
#objc func move(tap: UITapGestureRecognizer) {
performSegue(withIdentifier: "Animals", sender: nil)
}
}
The problem is that this code doesn't do what you think it does:
class ViewController: UIViewController {
let tapGesture = UIGestureRecognizer(target: self, action: #selector(ViewController.move(tap:)))
Your let tapGesture is an instance property declaration, and what follows the equal sign is its initializer. But you can't speak of self in an instance property initializer; there is no instance yet. So self here is taken to be the class. Thus, your tap gesture recognizer "works", but the move message is not sent to your ViewController instance; in effect, it is sent into empty space.
To fix this, you can initialize tapGesture at a time when self does exist. For example:
class ViewController: UIViewController {
let tapGesture : UIGestureRecognizer!
func viewDidLoad() {
self.tapGesture = UITapGestureRecognizer(target: self, action: #selector(ViewController.move(tap:)))

How to add button target function in IBAction method

I am using SWRevealViewController for side menu. while i click on menuBtn, im performing right toggle operation. I want the same when i swipe right Can any one Please Help me with it.
class Invoice: UIViewController {
#IBOutlet weak var menuBtn: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
let revealViewController = self.revealViewController()
menuBtn.addTarget(revealViewController, action: #selector(SWRevealViewController.rightRevealToggle(_:)), for: .touchUpInside)
}
#IBAction func swipeGesture(_ sender: UISwipeGestureRecognizer) {
print("Swiped")
//I want same action as i clicked on mentBtn
}
}
Something like this should work:
#IBAction func swipeGesture(_ sender: UISwipeGestureRecognizer) {
self.revealViewController().rightRevealToggle(self.menuBtn)
}

Passing uibutton tag through UILongPressGestureRecognizer?

I am trying to use the long press button function but am not sure how to pass the tag of the button to the function. I have an array of buttons called ChannelButton. The long button press works with the code below.
for button in ChannelButton {
let longPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress(sender:)))
button.addGestureRecognizer(longPressGestureRecognizer)
}
func handleLongPress(sender: UILongPressGestureRecognizer) {
doSomeFunction(NeedToPassTheButtonsTagHere)
}
But I need it to modify it to be something like this
for button in ChannelButton {
let longPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress(sender:, button.tag)))
button.addGestureRecognizer(longPressGestureRecognizer)
}
func handleLongPress(sender: UILongPressGestureRecognizer, buttontag) {
doSomeFunction(buttontag)
}
I know this doesn't work but I'm not sure how to go about it.
A UIGestureRecognizer has a view property that is the view that it is attached to. In your case, it will be your button. Use it to get to your button's tag:
func handleLongPress(sender: UILongPressGestureRecognizer) {
guard let button = sender.view as? UIButton else { return }
doSomeFunction(button.tag)
}
You're trying to add an EXTRA parameter (an int) to an IBAction selector. You can't do that. IBActions have one of 3 selectors:
#IBAction func actionNoParams() {
}
#IBAction func actionWSender(_ sender: Any) {
}
#IBAction func actionWSenderAndEvent(_ sender: Any, forEvent event: UIEvent) {
}
One solution would be to look for the location of your long press gesture, and then check what button has that location.
func handleLongPress(sender: UILongPressGestureRecognizer) {
if sender.state == UIGestureRecognizerState.began {
let location = sender.location(in: self.view)
for button in ChannelButton {
if button.frame.contains(location) {
//This is the button that is pressed
//Do stuff
}
}
}
}
Remember to conform to UIGestureRecognizerDelegate

UILongPressGesture gets called twice

So when ever I long press on a button, it recognizes the long press, but "test" gets called twice. How do I prevent that from happening?
#IBOutlet weak var button2: UIButton!
func longPressMe(){
print("test")
}
func longPressGes(){
let longpress = UILongPressGestureRecognizer(target: self, action: "longPressMe")
longpress.minimumPressDuration = 1
button2.addGestureRecognizer(longpress)
}
override func viewDidLoad() {
super.viewDidLoad()
longPressGes()
}
You have to check the state of the gesture recognizer. Change longPressMe() to something like this:
func longPressMe(recognizer: UILongPressGestureRecognizer) {
guard recognizer.state == .Began else { return }
// do stuff here
}
Have a try, here is how to use #selector:
func longPressMe(recognizer: UILongPressGestureRecognizer) {
// do stuff here
}
func longPressGes(){
let longpress = UILongPressGestureRecognizer(target: self, action: #selector(yourViewController.longPressMe(_:)))
longpress.minimumPressDuration = 1
button2.addGestureRecognizer(longpress)
}