skip to Main Content

I have a custom UIView class called SortView with two radio buttons and neither of their respective selector functions are being called when I click on them. I have added an instance of the SortView class to a parent class with view.addView(). Here is my custom class:

class SortView: UIView {
    
    // MARK: - Properties
    
    lazy var driverSortRadioButton: UIButton = {
        let button = UIButton(type: .system)
        button.setImage(UIImage(named: "Radio Button - Unselected"), for: .normal)
        button.setDimensions(height: 25, width: 25)
        button.backgroundColor = .clear
        button.contentMode = .scaleAspectFill
        button.addTarget(self, action: #selector(handleDriverSortRadioButton), for: .touchUpInside)
        return button
    }()

    lazy var pickupTimeSortRadioButton: UIButton = {
        let button = UIButton(type: .system)
        button.setImage(UIImage(named: "Radio Button - Unselected"), for: .normal)
        button.setDimensions(height: 25, width: 25)
        button.backgroundColor = .clear
        button.contentMode = .scaleAspectFill
        button.addTarget(self, action: #selector(handlePickupTimeSortRadioButton), for: .touchUpInside)
        return button
    }()

    private let driverSortTitleLabel: UILabel = {
        let label = UILabel()
        label.text = "Sort by driver:"
        label.textAlignment = .left
        label.textColor = .white
        label.font = UIFont(name: "AvenirNext-DemiBold", size: 18)
        label.backgroundColor = .clear
        return label
    }()

    private let pickupTimeSortTitleLabel: UILabel = {
        let label = UILabel()
        label.text = "Sort by pickup time:"
        label.textAlignment = .left
        label.textColor = .white
        label.font = UIFont(name: "AvenirNext-DemiBold", size: 18)
        label.backgroundColor = .clear
        return label
    }()
    
    private let driverSortTextField: UITextField = {
        let tf = UITextField()
        tf.textColor = .black
        tf.textAlignment = .center
        tf.placeholder = "Louise"
        tf.font = UIFont(name: "AvenirNext-DemiBold", size: 15)
        tf.backgroundColor = UIColor(white: 0.95, alpha: 1.0)
        tf.setWidth(width: 150)
        tf.layer.cornerRadius = 5
        return tf
    }()

    private let pickupTimeSortTextField: UITextField = {
        let tf = UITextField()
        tf.textColor = .black
        tf.textAlignment = .center
        tf.placeholder = "2:00pm"
        tf.font = UIFont(name: "AvenirNext-DemiBold", size: 15)
        tf.backgroundColor = UIColor(white: 0.95, alpha: 1.0)
        tf.setWidth(width: 150)
        tf.layer.cornerRadius = 5
        return tf
    }()
    
    private enum radioButtonStates {
        case driver
        case pickupTime
    }
    
    private var radioButtonState = radioButtonStates.driver
    
    // MARK: - Lifecycle
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        configureUI()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    // MARK: - Selectors
    
    @objc func handleDriverSortRadioButton() {
        print("DEBUG: driver sort radio button clicked")
        if radioButtonState != .driver {
            pickupTimeSortRadioButton.setImage(UIImage(named: "Radio Button - Unselected"), for: .normal)
            pickupTimeSortTextField.isEnabled = false
            pickupTimeSortTextField.text = ""
            
            radioButtonState = .driver
            driverSortRadioButton.setImage(UIImage(named: "Radio Button - Selected"), for: .normal)
            driverSortTextField.isEnabled = true
            driverSortTextField.text = ""
        }

    }

    @objc func handlePickupTimeSortRadioButton() {
        print("DEBUG: pickup time sort radio button clicked")
        if radioButtonState != .pickupTime {

            driverSortRadioButton.setImage(UIImage(named: "Radio Button - Unselected"), for: .normal)
            driverSortTextField.isEnabled = false
            driverSortTextField.text = ""

            radioButtonState = .pickupTime
            pickupTimeSortRadioButton.setImage(UIImage(named: "Radio Button - Selected"), for: .normal)
            pickupTimeSortTextField.isEnabled = true
            pickupTimeSortTextField.text = ""
        }
    }

    // MARK: - Helper Functions
    
    private func configureUI() {
        
        let driverSortStackView = UIStackView(arrangedSubviews: [driverSortRadioButton,
                                                                driverSortTitleLabel,
                                                                driverSortTextField])
        driverSortStackView.axis = .horizontal
        driverSortStackView.distribution = .fill
        driverSortStackView.spacing = 5

        let pickupTimeSortStackView = UIStackView(arrangedSubviews: [pickupTimeSortRadioButton,
                                                                     pickupTimeSortTitleLabel,
                                                                     pickupTimeSortTextField])
        pickupTimeSortStackView.axis = .horizontal
        pickupTimeSortStackView.distribution = .fill
        pickupTimeSortStackView.spacing = 5

        let stackView = UIStackView(arrangedSubviews:[driverSortStackView,
                                                      pickupTimeSortStackView])
        stackView.axis = .vertical
        stackView.distribution = .fill
        stackView.spacing = 10
        
        self.addSubview(stackView)
        stackView.centerX(inView: self)
        stackView.centerY(inView: self)
    }
}

The functions which are not being called are handleDriverSortRadioButton and handlePickupTimeSortRadioButton. Here is instantiation:

private lazy var sortView = SortView()

and here is where I use it in my parent UIViewController class:

    view.addSubview(sortView)
        sortView.anchor(top:tableView.bottomAnchor,
                        left: view.leftAnchor,
                        right: view.rightAnchor,
                        paddingTop: 40,
                        paddingLeft: 32,
                        paddingRight: 32)

2

Answers


  1. Chosen as BEST ANSWER

    Fixed it by adding with and height to the bottom stack view

            sortView.anchor(top:tableView.bottomAnchor,
                            left: view.leftAnchor,
                            right: view.rightAnchor,
                            paddingTop: 40,
                            paddingLeft: 32,
                            paddingRight: 32,
                            width: view.frame.width,
                            height: 100)
    

  2. I’m going to guess that the problem is that a containing view (perhaps one of the stack views) has zero size. The result would be that its subviews are visible but not tappable.

    Here is a debugging utility method you can use to track down this sort of thing:

    extension UIView {
        @objc func reportSuperviews(filtering:Bool = true) {
            var currentSuper : UIView? = self.superview
            print("reporting on (self)n")
            while let ancestor = currentSuper {
                let ok = ancestor.bounds.contains(ancestor.convert(self.frame, from: self.superview))
                let report = "it is (ok ? "inside" : "OUTSIDE") (ancestor)n"
                if !filtering || !ok { print(report) }
                currentSuper = ancestor.superview
            }
        }
    }
    

    Wait until your interface is all set up and the buttons are untappable, and then call that on one of the untappable buttons to get a report in the console.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search