DatePicker 在 iPhone 上位于 UINavigationBar 下,在 iPad 上运行良好

DatePicker goes under UINavigationBar on iPhone, works well on iPad

我有以下 DatePickerController 代码:

import UIKit

@objc protocol DatePickerControllerDelegate: AnyObject {
    func datePicker(controller: DatePickerController, didSelect date: Date)
    func datepickerDidDismiss(controller: DatePickerController)
}

final class DatePickerController: UIViewController {
    @objc weak var delegate: DatePickerControllerDelegate?

    @objc public var date: Date {
        get {
            return datePicker.date
        }
        set(value) {
            datePicker.setDate(value, animated: false)
        }
    }

    @objc public lazy var datePicker: UIDatePicker = {
        let v = UIDatePicker()
        v.datePickerMode = .date
        return v
    }()

    override var preferredContentSize: CGSize {
        get {
            return datePicker.frame.size
        }

        set(newValue) {
            super.preferredContentSize = newValue
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        view.addSubview(datePicker)
        datePicker.autoresizingMask = [.flexibleTopMargin, .flexibleRightMargin, .flexibleLeftMargin, .flexibleBottomMargin]
        view.backgroundColor = .white
        navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done,
                                                            target: self,
                                                            action: #selector(DatePickerController.doneButtonDidTap))

        navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel,
                                                           target: self,
                                                           action: #selector(DatePickerController.cancelButtonDidTap))
    }

    @objc private func doneButtonDidTap() {
        delegate?.datePicker(controller: self, didSelect: date)
    }

    @objc private func cancelButtonDidTap() {
        dismiss(animated: true, completion: nil)
        delegate?.datepickerDidDismiss(controller: self)
    }
}

它在 iPad:

上运行良好

但是,在 iPhone 上,选择器向上滑动到 UINavigationBar 下方:

用于显示 DatePickerController 的代码完全相同,两种情况下的样式都是 UIModalPresentationStylePopover

更新:显示 DatePickerController 的代码:

  @objc func presentDatePicker() {
    let picker = DatePickerController()
    let navC = UINavigationController(rootViewController: picker)
    present(navC, animated: true, completion: nil)
  }

已使用 AutoLayout 修复:

private func configureLayout() {
    datePicker.translatesAutoresizingMaskIntoConstraints = false
    [datePicker.topAnchor.constraint(equalTo: view.layoutMarginsGuide.topAnchor),
     datePicker.leadingAnchor.constraint(equalTo: view.leadingAnchor),
     datePicker.trailingAnchor.constraint(equalTo: view.trailingAnchor),]
        .forEach{[=10=].isActive = true}
}