点击按钮直接打开 DatePicker 弹出窗口

Open DatePicker popup directly on button tap

尝试在点击按钮时打开日期选择器弹出窗口,但它显示的是标签而不是选择器,点击该标签时选择器会打开。下面是代码:

 @IBAction func changeMonth(_ sender: Any) {
     
    let picker : UIDatePicker = UIDatePicker()
    picker.datePickerMode = UIDatePicker.Mode.date
    picker.addTarget(self, action: #selector(dueDateChanged(sender:)), for: UIControl.Event.valueChanged)
        let pickerSize : CGSize = picker.sizeThatFits(CGSize.zero)
        picker.frame = CGRect(x:0.0, y:250, width:pickerSize.width, height:460)
        
        self.view.addSubview(picker)
}

@objc func dueDateChanged(sender:UIDatePicker){
    let dateFormatter = DateFormatter()
    dateFormatter.dateStyle = .none
    dateFormatter.timeStyle = .none
btnMonth.setTitle(dateFormatter.string(from: sender.date), for: .normal)
}

需要这个才能在点击按钮时打开:

但显示的是:

点击此日期标签后,选择器将打开。我不明白为什么选择器不直接打开。请指导上面代码有什么问题。

这是一个非常简单的示例,将日期选择器嵌入到视图中,然后在点击按钮时显示/隐藏该视图:

class MyDatePicker: UIView {
    
    var changeClosure: ((Date)->())?
    var dismissClosure: (()->())?

    let dPicker: UIDatePicker = {
        let v = UIDatePicker()
        return v
    }()
    override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        commonInit()
    }
    func commonInit() -> Void {
        let blurEffect = UIBlurEffect(style: .dark)
        let blurredEffectView = UIVisualEffectView(effect: blurEffect)

        let pickerHolderView: UIView = {
            let v = UIView()
            v.backgroundColor = .white
            v.layer.cornerRadius = 8
            return v
        }()
        
        [blurredEffectView, pickerHolderView, dPicker].forEach { v in
            v.translatesAutoresizingMaskIntoConstraints = false
        }

        addSubview(blurredEffectView)
        pickerHolderView.addSubview(dPicker)
        addSubview(pickerHolderView)
        
        NSLayoutConstraint.activate([
            
            blurredEffectView.topAnchor.constraint(equalTo: topAnchor),
            blurredEffectView.leadingAnchor.constraint(equalTo: leadingAnchor),
            blurredEffectView.trailingAnchor.constraint(equalTo: trailingAnchor),
            blurredEffectView.bottomAnchor.constraint(equalTo: bottomAnchor),

            pickerHolderView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 20.0),
            pickerHolderView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -20.0),
            pickerHolderView.centerYAnchor.constraint(equalTo: centerYAnchor),

            dPicker.topAnchor.constraint(equalTo: pickerHolderView.topAnchor, constant: 20.0),
            dPicker.leadingAnchor.constraint(equalTo: pickerHolderView.leadingAnchor, constant: 20.0),
            dPicker.trailingAnchor.constraint(equalTo: pickerHolderView.trailingAnchor, constant: -20.0),
            dPicker.bottomAnchor.constraint(equalTo: pickerHolderView.bottomAnchor, constant: -20.0),

        ])
        
        if #available(iOS 14.0, *) {
            dPicker.preferredDatePickerStyle = .inline
        } else {
            // use default
        }
        
        dPicker.addTarget(self, action: #selector(didChangeDate(_:)), for: .valueChanged)
        
        let t = UITapGestureRecognizer(target: self, action: #selector(tapHandler(_:)))
        blurredEffectView.addGestureRecognizer(t)
    }
    
    @objc func tapHandler(_ g: UITapGestureRecognizer) -> Void {
        dismissClosure?()
    }
    
    @objc func didChangeDate(_ sender: UIDatePicker) -> Void {
        changeClosure?(sender.date)
    }
    
}

class ViewController: UIViewController {
    
    let myPicker: MyDatePicker = {
        let v = MyDatePicker()
        return v
    }()
    let myButton: UIButton = {
        let v = UIButton()
        v.setTitle("Show Picker", for: [])
        v.setTitleColor(.white, for: .normal)
        v.setTitleColor(.lightGray, for: .highlighted)
        v.backgroundColor = .blue
        return v
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        [myButton, myPicker].forEach { v in
            v.translatesAutoresizingMaskIntoConstraints = false
            view.addSubview(v)
        }
        let g = view.safeAreaLayoutGuide
        NSLayoutConstraint.activate([
            
            // custom picker view should cover the whole view
            myPicker.topAnchor.constraint(equalTo: g.topAnchor),
            myPicker.leadingAnchor.constraint(equalTo: g.leadingAnchor),
            myPicker.trailingAnchor.constraint(equalTo: g.trailingAnchor),
            myPicker.bottomAnchor.constraint(equalTo: g.bottomAnchor),
            
            myButton.centerXAnchor.constraint(equalTo: g.centerXAnchor),
            myButton.topAnchor.constraint(equalTo: g.topAnchor, constant: 40.0),
            myButton.widthAnchor.constraint(equalTo: g.widthAnchor, multiplier: 0.75),
            
        ])
        
        // hide custom picker view
        myPicker.isHidden = true
        
        // add closures to custom picker view
        myPicker.dismissClosure = { [weak self] in
            guard let self = self else {
                return
            }
            self.myPicker.isHidden = true
        }
        myPicker.changeClosure = { [weak self] val in
            guard let self = self else {
                return
            }
            print(val)
            // do something with the selected date
        }
        
        // add button action
        myButton.addTarget(self, action: #selector(tap(_:)), for: .touchUpInside)
    }
    
    @objc func tap(_ sender: Any) {
        myPicker.isHidden = false
    }
    
}

这是开始时的样子:

点击按钮将显示自定义视图:

这是它在 iOS 13 上的样子(在新的 UI 之前):