Custom UIView: UIButton addTarget not called

2019-08-23 03:52发布

问题:

My problem is that I have a custom UIView, which is representing a popup. Inside this view I want to have a slider, which has a label that gets updated every time I drag the slider around. The slider logic works, at least when I'm using it in a ViewController directly, but not with with my custom view. Specifically, the method specified in addTarget doesn't get called at all. I also tried setting the backgroundColor of the slider to something, and it actually showed up, meaning it has a frame. So, what am I missing here? I had a similar problem a lot of times with UIButton, etc. in custom UIView subclasses.

class PriceVoteController: UIView {

var parentView: UIView = UIView()

let slider: UISlider = {
    let slider = UISlider()
    slider.isContinuous = true
    slider.minimumValue = 1
    slider.maximumValue = 3
    slider.setMinimumTrackImage(#imageLiteral(resourceName: "minimumSliderTrackImage").resizableImage(withCapInsets: UIEdgeInsets(top: 0, left: 9, bottom: 0, right: 9)), for: .normal)
    slider.setMaximumTrackImage(#imageLiteral(resourceName: "maximumSliderTrackImage").resizableImage(withCapInsets: UIEdgeInsets(top: 0, left: 9, bottom: 0, right: 9)), for: .normal)

    let sliderThumb = #imageLiteral(resourceName: "sliderThumImage")
    slider.setThumbImage(sliderThumb, for: .normal)

    slider.addTarget(self, action: #selector(adjustPriceLabel), for: .valueChanged)

    slider.setValue(2.0, animated: true)

    return slider
}()

let priceLabel: UILabel = {
    let label = UILabel()
    label.textAlignment = .center
    return label
}()

let blackView: UIView = {
    let view = UIView()
    view.backgroundColor = .black
    view.alpha = 0.2
    return view
}()

let popUpView: UIView = {
    let view = UIView()
    view.layer.backgroundColor = UIColor.white.cgColor
    view.layer.cornerRadius = 10
    return view
}()

@objc fileprivate func adjustPriceLabel() {
    print("adjust label")
    priceLabel.text = String(format: "%.1f", slider.value)
    priceLabelLeftConstraint.constant = getXPositionForSliderValue()
}

fileprivate func getXPositionForSliderValue() -> CGFloat {
    guard let currentThumbImage = slider.currentThumbImage else { return 0 }
    let sliderRange = slider.frame.size.width - currentThumbImage.size.width;
    let sliderOrigin = slider.frame.origin.x + (currentThumbImage.size.width / 2.0);

    let sliderValueToPixels = ((CGFloat(slider.value - slider.minimumValue)/CGFloat(slider.maximumValue - slider.minimumValue)) * sliderRange) + sliderOrigin;

    return sliderValueToPixels;
}

var priceLabelLeftConstraint: NSLayoutConstraint = NSLayoutConstraint()

override init(frame: CGRect) {
    super.init(frame: frame)

    self.isUserInteractionEnabled = true
}

fileprivate func setupSlider() {
    self.popUpView.addSubview(slider)
    slider.anchor(top: self.popUpView.topAnchor, left: self.popUpView.leftAnchor, bottom: nil, right: self.popUpView.rightAnchor, paddingTop: 10, paddingLeft: 50, paddingBottom: 0, paddingRight: 50, width: 0, height: 0)

    self.popUpView.addSubview(priceLabel)
    priceLabel.text = String(slider.value)

    priceLabel.anchor(top: slider.bottomAnchor, left: nil, bottom: nil, right: nil, paddingTop: 10, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: 0, height: 0)
    priceLabelLeftConstraint = priceLabel.centerXAnchor.constraint(equalTo: self.popUpView.leftAnchor, constant: getXPositionForSliderValue())
    priceLabelLeftConstraint.isActive = true
}

func showOn(view: UIView) {
    parentView = view

    parentView.addSubview(self.popUpView)

    self.popUpView.anchor(top: nil, left: nil, bottom: nil, right: nil, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: view.frame.width - 100, height: 200)
    self.popUpView.centerXAnchor.constraint(equalTo: parentView.centerXAnchor).isActive = true
    self.popUpView.centerYAnchor.constraint(equalTo: parentView.centerYAnchor).isActive = true

    setupSlider()
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}
}

I really hope that someone can help me with this, as I've tried to figure this out for the past hours... and no solution :/ As I said, the method gets called when everything is inside a ViewController and its view, but not with the custom UIView.

And by the way, the parentView property is the main view of the viewController, where the custom UIView gets initialized. I initialize it with the empty constructor and then call show() with the ViewController's view.

Thanks for your help! - Robert

回答1:

So, finally I got the solution... For everybody that faces the same issue: Look at your view hierarchy. I was missing the linkn between my popUpView and my customView, thats why the touch events weren't triggered properly. Another mistake was that the popUp was never anchored properly and didn't have an own frame... That's why the slider wasn't operatable at all. I hope this helps some of you guys!