iOS开发:实现UITableView按事件时间自动排序与冲突校验
完整实现方案:UITableView事件自动排序+时间冲突校验
一、修正SessionModel的Date类型定义
直接把时间字段设为Date类型,避免字符串转Date的额外麻烦:
import Foundation struct SessionModel: Codable { var startTime: Date var endTime: Date var title: String var location: String }
二、解决Date与UILabel的显示问题
UILabel只能显示字符串,用DateFormatter把Date转成可读字符串,建议全局初始化一个避免重复创建:
// 可以放在ViewController或者单独的工具文件里 let dateFormatter: DateFormatter = { let formatter = DateFormatter() formatter.dateFormat = "yyyy-MM-dd HH:mm" // 可根据需求自定义格式 formatter.locale = Locale.current return formatter }()
然后在PrototypeCell里完成数据绑定:
import UIKit class PrototypeCell: UITableViewCell { @IBOutlet weak var titleLabel: UILabel! @IBOutlet weak var timeLabel: UILabel! @IBOutlet weak var locationLabel: UILabel! func configure(with session: SessionModel) { titleLabel.text = session.title locationLabel.text = session.location // 把Date转成字符串显示 let startStr = dateFormatter.string(from: session.startTime) let endStr = dateFormatter.string(from: session.endTime) timeLabel.text = "\(startStr) - \(endStr)" } }
三、事件自动排序逻辑
每次添加新事件后,对数据源数组按startTime升序排序,再刷新TableView。以下是ViewController里的核心代码:
class ViewController: UIViewController { @IBOutlet weak var tableView: UITableView! var sessions: [SessionModel] = [] // 数据源数组 @IBAction func addButtonTapped(_ sender: UIBarButtonItem) { let addVC = storyboard?.instantiateViewController(withIdentifier: "AddSessionViewController") as! AddSessionViewController // 用闭包接收新事件 addVC.onSessionAdded = { [weak self] newSession in guard let self = self else { return } // 先校验冲突,无冲突再添加排序 if !self.isTimeConflict(with: newSession) { self.sessions.append(newSession) // 按开始时间升序排序 self.sessions.sort { $0.startTime < $1.startTime } self.tableView.reloadData() } else { // 弹出冲突提示 let alert = UIAlertController(title: "时间冲突", message: "该时间段已有其他事件,请重新选择", preferredStyle: .alert) alert.addAction(UIAlertAction(title: "确定", style: .default)) self.present(alert, animated: true) } } present(addVC, animated: true) } }
四、时间冲突校验逻辑
在ViewController里添加校验方法,判断新事件是否和已有事件时间重叠:
private func isTimeConflict(with newSession: SessionModel) -> Bool { let newStart = newSession.startTime let newEnd = newSession.endTime for session in sessions { let existingStart = session.startTime let existingEnd = session.endTime // 三种冲突情况:新事件开始在已有事件区间内、结束在区间内、完全覆盖已有事件 if (newStart >= existingStart && newStart < existingEnd) || (newEnd > existingStart && newEnd <= existingEnd) || (newStart <= existingStart && newEnd >= existingEnd) { return true } } return false }
五、AddSessionViewController表单处理
修正表单输入校验,直接用UIDatePicker获取Date类型的时间:
class AddSessionViewController: UIViewController { @IBOutlet weak var titleTextField: UITextField! @IBOutlet weak var locationTextField: UITextField! @IBOutlet weak var startTimePicker: UIDatePicker! @IBOutlet weak var endTimePicker: UIDatePicker! // 定义回调闭包,传递新事件 var onSessionAdded: ((SessionModel) -> Void)? @IBAction func addButtonTapped(_ sender: UIButton) { // 校验必填项 guard let title = titleTextField.text, !title.isEmpty, let location = locationTextField.text, !location.isEmpty else { let alert = UIAlertController(title: "提示", message: "请填写完整事件信息", preferredStyle: .alert) alert.addAction(UIAlertAction(title: "确定", style: .default)) present(alert, animated: true) return } let startTime = startTimePicker.date let endTime = endTimePicker.date // 校验结束时间不能早于开始时间 guard endTime > startTime else { let alert = UIAlertController(title: "时间错误", message: "结束时间必须晚于开始时间", preferredStyle: .alert) alert.addAction(UIAlertAction(title: "确定", style: .default)) present(alert, animated: true) return } // 创建事件模型并回调 let newSession = SessionModel(startTime: startTime, endTime: endTime, title: title, location: location) onSessionAdded?(newSession) dismiss(animated: true) } }
六、ViewController的TableView数据源方法
确保Cell配置正确:
extension ViewController: UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return sessions.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "PrototypeCell", for: indexPath) as! PrototypeCell cell.configure(with: sessions[indexPath.row]) return cell } }
内容的提问来源于stack exchange,提问作者CalebGates
相关产品推荐
相关产品推荐

