You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift多条目提交时Inline DatePicker显示异常问题排查

iOS 14+ 内联日期选择器重复显示时被截断的问题解决

问题场景

在记录拜日式(suryanamaskar)次数的页面中,点击日期按钮弹出iOS 14+的inline样式日期选择器,首次显示正常,但添加新条目或再次点击日期按钮时,选择器会被截断无法正常显示;改用wheels样式则无此问题。

核心问题分析

  1. 全局Picker实例重复添加:代码中datePicker是全局常量,每次调用showDatePicker()都会将同一个Picker实例重复添加到viewPicker中,导致视图层级混乱。
  2. 固定Frame适配失效:inline样式日期选择器的高度是动态的,使用固定frame布局无法适配其真实高度,导致显示截断。
  3. Picker显示逻辑错误:重复创建viewPicker实例而非复用已有实例,引发视图叠加和布局异常。

修复方案

1. 修改属性定义

将全局datePicker改为可选类型,避免重复使用同一个实例:

var datePicker: UIDatePicker?

2. 重构showDatePicker()方法

使用AutoLayout替代固定Frame,实现动态适配,并复用已有Picker容器:

func showDatePicker(){
    // 复用已有的picker容器,避免重复创建
    if let existingPicker = viewPicker {
        existingPicker.isHidden = false
        return
    }
    
    viewPicker = UIView()
    viewPicker?.backgroundColor = .white
    viewPicker?.clipsToBounds = true
    viewPicker?.translatesAutoresizingMaskIntoConstraints = false
    
    // 创建新的日期选择器实例
    datePicker = UIDatePicker()
    guard let picker = datePicker else { return }
    picker.datePickerMode = .date
    picker.minimumDate = Calendar.current.date(byAdding: .month, value: -2, to: Date())
    picker.maximumDate = Date()
    picker.backgroundColor = .white
    
    if #available(iOS 14.0, *) {
        picker.preferredDatePickerStyle = .inline
    } else if #available(iOS 13.4, *) {
        picker.preferredDatePickerStyle = .wheels
    }
    
    picker.addTarget(self, action: #selector(datePickerValueChanged(_:)), for: .valueChanged)
    picker.translatesAutoresizingMaskIntoConstraints = false
    
    // 构建工具栏
    let toolbar = UIToolbar()
    toolbar.sizeToFit()
    toolbar.translatesAutoresizingMaskIntoConstraints = false
    let doneButton = UIBarButtonItem(title: "完成", style: .plain, target: self, action: #selector(donedatePicker))
    let spaceButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
    let cancelButton = UIBarButtonItem(title: "取消", style: .plain, target: self, action: #selector(cancelDatePicker))
    toolbar.setItems([doneButton, spaceButton, cancelButton], animated: false)
    
    // 添加子视图并设置约束
    viewPicker?.addSubview(toolbar)
    viewPicker?.addSubview(picker)
    view.addSubview(viewPicker!)
    
    NSLayoutConstraint.activate([
        // 容器视图约束:底部对齐父视图,左右铺满,高度自适应
        viewPicker!.bottomAnchor.constraint(equalTo: view.bottomAnchor),
        viewPicker!.leadingAnchor.constraint(equalTo: view.leadingAnchor),
        viewPicker!.trailingAnchor.constraint(equalTo: view.trailingAnchor),
        
        // 工具栏约束:顶部对齐容器,左右铺满,高度固定
        toolbar.topAnchor.constraint(equalTo: viewPicker!.topAnchor),
        toolbar.leadingAnchor.constraint(equalTo: viewPicker!.leadingAnchor),
        toolbar.trailingAnchor.constraint(equalTo: viewPicker!.trailingAnchor),
        toolbar.heightAnchor.constraint(equalToConstant: 50),
        
        // 日期选择器约束:工具栏下方布局,左右留边,底部对齐容器
        picker.topAnchor.constraint(equalTo: toolbar.bottomAnchor, constant: 10),
        picker.leadingAnchor.constraint(equalTo: viewPicker!.leadingAnchor, constant: 10),
        picker.trailingAnchor.constraint(equalTo: viewPicker!.trailingAnchor, constant: -10),
        picker.bottomAnchor.constraint(equalTo: viewPicker!.bottomAnchor, constant: -10)
    ])
}

3. 简化日期按钮点击逻辑

@objc func onDateClick(_ sender: UIButton) {
    btnIndex = sender.tag
    view.endEditing(true)
    
    // 切换picker的显示/隐藏状态,避免重复创建
    if let picker = viewPicker {
        picker.isHidden = !picker.isHidden
    } else {
        showDatePicker()
    }
}

4. 修正事件绑定错误

将原代码中错误的目标类AddMemberStep1VC改为当前类:

picker.addTarget(self, action: #selector(datePickerValueChanged(_:)), for: .valueChanged)

关键修复说明

  • 复用viewPicker实例,避免重复创建视图导致的层级混乱
  • 使用AutoLayout实现动态布局,适配inline样式日期选择器的可变高度
  • 每次显示日期选择器时创建新实例,避免同一个Picker被多次添加到视图中
  • 简化显示/隐藏逻辑,提升交互流畅度

内容的提问来源于stack exchange,提问作者user20925367

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 04:20:52