将项目筛选到节

  • 本文关键字:筛选 项目 swift
  • 更新时间 :
  • 英文 :


我想将属性为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中创建两个属性completednotCompleted,并将它们用作tableView数据源

class Manager {    
lazy var completed: [Task] = {
return tasks.filter({ !$0.isCompleted })
}()
lazy var notCompleted: [Task] = {
return tasks.filter({ $0.isCompleted })
}()
}

UITableViewDataSourceUITableViewDelegate方法,

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]调用它

最新更新