首页 > 解决方案 > UITableViewCell 中的 UIDatePicker 未正确显示并崩溃

问题描述

当用户选择行时,我尝试将 UIDatePicker 添加到 UITableViewCell 。我以编程方式将其添加到单元格中,并在单元格选择中切换其可见性。它在设备和模拟器上都可以正常工作。但是当我在 Xcode 中断开设备或按下停止并在模拟器中重新启动应用程序时 - UIDatePicker 被裁剪(部分可见)并在点击它时崩溃应用程序。

在此处输入图像描述

我试图在 tableview 控制器中这样做

    var groomingDatePicker: UIDatePicker = {
        let picker = UIDatePicker()
        picker.datePickerMode = .date
        return picker
    }()

在 cellForRow...

    let cell = UITableViewCell()
    cell.textLabel?.text = some text
    cell.backgroundColor = UIColor.white
    cell.selectionStyle = .none
            
    cell.contentView.addSubview(groomingDatePicker)
    groomingDatePicker.translatesAutoresizingMaskIntoConstraints = false
    groomingDatePicker.rightAnchor.constraint(equalTo: cell.rightAnchor, constant: -75).isActive = true
    groomingDatePicker.centerYAnchor.constraint(equalTo: cell.centerYAnchor).isActive = true
    groomingDatePicker.widthAnchor.constraint(equalToConstant: 150).isActive = true
    groomingDatePicker.heightAnchor.constraint(equalTo: cell.heightAnchor).isActive = true
    if petDefaults.bool(forKey: somekey) == true 
        {
        cell.accessoryType = UITableViewCell.AccessoryType.checkmark
        groomingDatePicker.isHidden = false
        } else {
        cell.accessoryType = UITableViewCell.AccessoryType.none
        groomingDatePicker.isHidden = true
        }
    return cell

我也尝试制作自定义 TableViewCell,结果是一样的

标签: swiftuidatepicker

解决方案


假设您需要的是一个提醒数组,您将需要一个简单的数据模型来保存数据,因为您的 tableView 不是数据存储,它只是数据的显示。单元格被重复使用,因此您不能期望在滚动时保留该值。每次显示单元格时,都必须将其视为全新的显示,这意味着您必须将日期保存在数组中。

假设您有一个像这样的简单提醒结构

struct ReminderDetails
{
    var description : String = ""
    var date        : Date   = Date() 
}

你有一个像这样声明的类变量

var reminders : [ReminderDetails] = []
// create some dummy data
reminders.append(ReminderDetails(description: "first thing to do", date: Date()))
reminders.append(ReminderDetails(description: "second thing to do", date: Date()))
reminders.append(ReminderDetails(description: "another thing to do", date: Date()))

然后当你创建你的单元格时,确保每次都设置提醒日期

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
    let cell = UITableViewCell()
    cell.textLabel?.text = reminders[indexPath.row].description
    cell.backgroundColor = UIColor.white
    cell.selectionStyle = .none

    let groomingDatePicker: UIDatePicker = UIDatePicker()
    groomingDatePicker.datePickerMode = .date
    groomingDatePicker.date = reminders[indexPath.row].date
    
    groomingDatePicker.tag = indexPath.row

    // update the stored value whenever the value is changed
    groomingDatePicker.addTarget(self, action: #selector(ViewController.datePickerValueChanged), for: UIControl.Event.valueChanged)
    
    
    cell.contentView.addSubview(groomingDatePicker)
    groomingDatePicker.translatesAutoresizingMaskIntoConstraints = false
    groomingDatePicker.rightAnchor.constraint(equalTo: cell.rightAnchor, constant: 0).isActive = true
    groomingDatePicker.centerYAnchor.constraint(equalTo: cell.centerYAnchor).isActive = true
    groomingDatePicker.widthAnchor.constraint(equalToConstant: 150).isActive = true
    groomingDatePicker.heightAnchor.constraint(equalTo: cell.heightAnchor).isActive = true
 
    if petDefaults.bool(forKey: somekey) == true
    {
        cell.accessoryType = UITableViewCell.AccessoryType.checkmark
        groomingDatePicker.isHidden = false
    } else {
        cell.accessoryType = UITableViewCell.AccessoryType.none
        groomingDatePicker.isHidden = true
    }
    return cell
}

当日期更新时,您需要采取一些措施,这就是

groomingDatePicker.addTarget(self, action: #selector(ViewController.datePickerValueChanged), for: UIControl.Event.valueChanged)

行用于 - 当日期更改时,datePickerValueChanged调用该函数,传入发送者,以便您可以访问sender.tag哪个让您知道该行,因此哪个控件已更新。

// date changed event
@objc func datePickerValueChanged(sender:UIDatePicker)
{
    // update the reminder date for the right entry, based on the sender tag
    reminders[sender.tag].date = sender.date
}

这只是更新类数组——如果你将它存储在数据库中,你将不得不在那里更新它——无论是每次更改某些内容时,还是作为最后的一个块。


推荐阅读