0

There are some similar questions out there on this, but they're in Obj-C and don't specifically answer my question.

I'm building a Tinder-like dating application with a button on the card that allows the current user to view more info about the user on the displayed card. I've written this button (moreInfoButton) programmatically and have it displayed on the card (UIView) without a problem. But when I click on the button, it does not function. I've tried isEnabled and isUserInteractionEnabled, but neither work. Here's my code:

import UIKit
import SDWebImage

class CardView: UIView {

var imageView = UIImageView(image: #imageLiteral(resourceName: "lady5c"))

var informationLabel = UILabel()

var images: [String]?

var userId: String?

var stackView: UIStackView?

let moreInfoButton: UIButton = {
    let button = UIButton(type: .system)
    button.setImage(#imageLiteral(resourceName: "info_icon").withRenderingMode(.alwaysOriginal), for: .normal)
    return button
}()

override init(frame: CGRect) {
    super.init(frame: frame)
    layer.cornerRadius = 15
    clipsToBounds = true

    imageView.contentMode = .scaleAspectFill
    addSubview(imageView)
    imageView.fillSuperview()

    addSubview(informationLabel)
    informationLabel.numberOfLines = 0
    informationLabel.anchor(top: nil, leading: leadingAnchor, bottom: bottomAnchor, trailing: trailingAnchor, padding: .init(top: 0, left: 16, bottom: 16, right: 16))
    informationLabel.text = ""
    informationLabel.textColor = .white
    informationLabel.layer.zPosition = 1

    addSubview(moreInfoButton)
    moreInfoButton.anchor(top: nil, leading: nil, bottom: bottomAnchor, trailing: trailingAnchor, padding: .init(top: 0, left: 0, bottom: 20, right: 20), size: .init(width: 50, height: 50))
    moreInfoButton.layer.zPosition = 1
    moreInfoButton.isUserInteractionEnabled = true

    // let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePan))
    // addGestureRecognizer(panGesture)
    addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleTap)))

}
2
  • if you want whole the view can click, you should add self.isUserInteractionEnabled = true in init Commented Jul 1, 2019 at 3:48
  • add action to your button Commented Jul 1, 2019 at 4:43

4 Answers 4

1

if you add a button programmatically, I think you should use addTarget instead of using whole uiview gesture. This makes button has a functionality without having any relation about view gestures.

lazy var button: UIButton = {
    let temp = UIButton(type: .system)
    temp.isUserInteractionEnabled = true
    temp.addTarget(self, action: someFunction, for: UIControl.Event.touchUpInside)
    return temp
}()
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you, but that still doesn't seem to work. This button, when tapped, is supposed to open a separate view controller containing the user's info (from the card). I forgot to mention that the UIView that displays the user's photo (upon which the button sits) is tappable so the current user can cycle through the user's photos (just like Tinder). Thus, when I tap the button, it recognizes it as in the "forward" half of the view and cycles to the next photo rather than executing the code for the button. Any suggestions?
Is it possible to share a drawing or something like that we can image for your exact needs ?
0

I think UITapGestureRecognizer conflict with button tap event. You can try use override touchesBegan event instead of tap gesture.

Comments

0

Disable cancelsTouchesInView property of the gesture. By default, I think it is set to true. This means that the gesture consumes the touch event and it is not passed on to the button

let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap))
tapGesture.cancelsTouchesInView = false
addGestureRecognizer(tapGesture)

Comments

0

UPDATE: Since the button is sitting on top of the tappable view, make sure the button is displayed in front of the tappable view. If you are using storyboard, the button should be listed below the tappable view.

Also, in your touchesBegan method, make sure you don't respond to touches inside your button:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    let touch = touches.first
    if touch?.view != button && touch?.view == tappableView {
        // Next picture
    }
}

If that still doesn't work, try this implementation of touchesBegan instead:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    let touch = touches.first
    if touch?.view == button {
        // performSegue or call button's target function
    } else if touch?.view == tappableView {
        // Next picture
    }
}

You are missing a target for your button:

moreInfoButton.addTarget(self, action: #selector(buttonTapped(_:)), forControlEvents: .TouchUpInside)

and a function to handle the tap:

@objc func buttonTapped(sender: UIButton!) {
    // action
}

1 Comment

Thank you, but that still doesn't seem to work. This button, when tapped, is supposed to open a separate view controller containing the user's info (from the card). I forgot to mention that the UIView that displays the user's photo (upon which the button sits) is tappable so the current user can cycle through the user's photos (just like Tinder). Thus, when I tap the button, it recognizes it as in the "forward" half of the view and cycles to the next photo rather than executing the code for the button. Any suggestions?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.