我想将属性为isCompleted = true
的项筛选到名称为Completed的节,将未完成项筛选到ToDo。如何渲染项目?
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 {
return manager.tasks.filter({$0.isCompleted == false}).count
} else {
return manager.tasks.filter({$0.isCompleted}).count
}
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
switch section {
case 0:
return "ToDo"
case 1:
return "Completed"
default:
return nil
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: Keys.cell.rawValue, for: indexPath) as! ToDoCell
let currentItem = manager.tasks[indexPath.row]
cell.titleLabel.text = currentItem.taskName
cell.descriptionLabel.text = currentItem.description
if manager.tasks[indexPath.row].description?.isEmpty ?? false {
cell.descLabelBottomConstraint.constant = 0
}
let accessoryType: UITableViewCell.AccessoryType = currentItem.isCompleted ? .checkmark : .none
cell.accessoryType = accessoryType
return cell
}
我想我需要将项目筛选到两个不同的数组中?但哪种方式最正确?
永远不要过滤numberOfRowsInSection
中的内容。不要这样做,这个方法经常被调用。
-
创建模型
struct Section { let title : String var items : [Task] }
-
声明数据源数组
var sections = [Section]()
-
在
viewDidLoad
中填充数组并重新加载表视图sections = [Section(title: "ToDo", items: manager.tasks.filter{!$0.isCompleted}), Section(title: "Completed", items: manager.tasks.filter{$0.isCompleted})] tableView.reloadData()
-
现在数据源方法变得非常干净(快速(
override func numberOfSections(in tableView: UITableView) -> Int { return sections.count } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return sections[section].items.count } override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { return sections[section].title } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: Keys.cell.rawValue, for: indexPath) as! ToDoCell let currentItem = sections[indexPath.section].items[indexPath.row] cell.titleLabel.text = currentItem.taskName cell.descriptionLabel.text = currentItem.description if currentItem.description?.isEmpty ?? false { cell.descLabelBottomConstraint.constant = 0 } // you have to add an else clause to set the constraint to the default value cell.accessoryType = currentItem.isCompleted ? .checkmark : .none return cell }
使用分区算法过滤项目O(n(仍然更有效
let p = manager.tasks.partition(by: { $0.completed })
sections = [Section(title: "ToDo", items: Array(manager.tasks[p...])),
Section(title: "Completed", items: Array(manager.tasks[..<p]))]
tableView.reloadData()
您可以在Manager
中创建两个属性completed
和notCompleted
,并将它们用作tableView
的数据源。
class Manager {
lazy var completed: [Task] = {
return tasks.filter({ !$0.isCompleted })
}()
lazy var notCompleted: [Task] = {
return tasks.filter({ $0.isCompleted })
}()
}
UITableViewDataSource
和UITableViewDelegate
方法,
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return section == 0 ? manager.notCompleted.count : manager.completed.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return section == 0 ? "Todo" : "Completed"
}
您希望您的原始dataSource是由两个不同数组组成的数组(一个已完成,一个未完成([[]]
我发现这个看起来很结实。然而,它返回了一个字典,但我为您稍微重写了一下:
extension Sequence {
func group<U: Hashable>(by key: (Iterator.Element) -> U) -> [[Iterator.Element]] {
return Dictionary.init(grouping: self, by: key).map({$0.value})
}
}
这样,当你在标题标题标题或cellForRowAt
时,你可以通过manager.task[indexPath.section][indexPath.item]
调用它