如何使用自定义模型类按部分按字母顺序对 tableView 中的数据进行排序?

Posted

技术标签:

【中文标题】如何使用自定义模型类按部分按字母顺序对 tableView 中的数据进行排序?【英文标题】:How do you sort data in a tableView alphabetically by section using a custom model class? 【发布时间】:2017-01-14 04:57:06 【问题描述】:

我是编码新手,一直在尝试按部分按字母顺序对我的 tableview 行中的数据(名称)进行排序。我设法创建了部分和索引,但不知道如何让名称进行排序;每个部分都有相同的 A-Z 名称列表。

我有一个名称模型类,其中包含对象:nameTitle、nameDetail、图像、纬度坐标和经度坐标。 tableView 显示 nameTitle.text。其余对象在另一个视图控制器中显示或访问。

这是来自我的 TableViewController 的示例代码:

import UIKit

class TableOfContentsVC: UIViewController, UITableViewDelegate,  UITableViewDataSource 

@IBAction func backButtonPressed(_ sender: Any) 

    dismiss(animated: false, completion: nil)



@IBOutlet weak var tableView: UITableView?

var name = [Name]()

override func viewDidLoad() 
    super.viewDidLoad()

    let cell001 = Name (nameTitle: "Acker" , nameDetail: "Details for Acker are listed here.", picture: UIImage (named: "somePicture.jpg"), latCoordinates: 38, longCoordinates: 119)

    name.append (cell001)

    let cell002 = Name (nameTitle: "Baker" , nameDetail: "Details for Baker are listed here.", picture: UIImage (named: "somePicture.jpg"), latCoordinates: 38, longCoordinates: 119)

    name.append (cell002)

    let cell003 = Name (nameTitle: "Caker" , nameDetail: "Details for Caker are listed here.", picture: UIImage (named: "somePicture.jpg"), latCoordinates: 38, longCoordinates: 119)

    name.append (cell003)

    let cell004 = Name (nameTitle: "Dacker" , nameDetail: "Details for Dacker are listed here.", picture: UIImage (named: "somePicture.jpg"), latCoordinates: 38, longCoordinates: 119)

    name.append (cell004)

    let cell005 = Name (nameTitle: "Ecker" , nameDetail: "Details for Ecker are listed here.", picture: UIImage (named: "somePicture.jpg"), latCoordinates: 38, longCoordinates: 119)

    name.append (cell005)

    let cell006 = Name (nameTitle: "Facker" , nameDetail: "Details for Facker are listed here.", picture: UIImage (named: "somePicture.jpg"), latCoordinates: 38, longCoordinates: 119)

    name.append (cell006)

func tableView(_ tableView: UITableView, sectionForSectionIndexTitle title: String, at index: Int) -> Int 
    let currentCollation = UILocalizedIndexedCollation.current() as UILocalizedIndexedCollation
    return currentCollation.section(forSectionIndexTitle: index)


func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? 
    let currentCollation = UILocalizedIndexedCollation.current() as UILocalizedIndexedCollation
    let sectionTitles = currentCollation.sectionTitles as NSArray
    return sectionTitles.object(at: section) as? String



func sectionIndexTitles(for tableView: UITableView) -> [String]? 
    let currentCollation = UILocalizedIndexedCollation.current() as UILocalizedIndexedCollation
    return (currentCollation.sectionIndexTitles as NSArray) as? [String]




func numberOfSections(in tableView: UITableView) -> Int 
    let currentCollation = UILocalizedIndexedCollation.current() as UILocalizedIndexedCollation
    let sectionTitles = currentCollation.sectionTitles as NSArray
    return sectionTitles.count




func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 

    if let cell = tableView.dequeueReusableCell(withIdentifier: "NameCell", for: indexPath) as? NameCell 

        let name = Name [indexPath.row]

        cell.updateUI(name: name)

    return cell


     else 

        return UITableViewCell()

    



func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 

            return name.count




func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) 

    let name = names [indexPath.row]
    performSegue(withIdentifier: "ContentVC", sender: name)



override func prepare(for segue: UIStoryboardSegue, sender: Any?) 

    if let destination = segue.destination as? ContentVC 

        if let name = sender as? Name 
            destination.name = name
        
    
  

除了让名称按字母顺序显示在相应部分之外,一切都很好。我已经尝试了大约 10 种不同的方法来让它发挥作用,但没有任何帮助。任何建议将不胜感激。提前致谢!

【问题讨论】:

【参考方案1】:

你做错了。您没有使用您的数据来生成索引。

假设您有一个数据数组var name: [Name]

    定义每个Name 所属的部分:
extension Name 
    var titleFirstLetter: String 
        return String(self.nameTitle[self.nameTitle.startIndex]).uppercased()
    

    根据您的数据生成索引
// all the first letters in your data
let firstLetters = names.map  $0.titleFirstLetter 
// some letters appear multiple times, let's remove duplicates
let uniqueFirstLetters = Array(Set(firstLetters))
// sort them
// this is your index
let sortedFirstLetters = uniqueFirstLetters.sorted()
    生成部分
let sections: [[Name]] = sortedFirstLetters.map  firstLetter in
    return names
        .filter  $0.titleFirstLetter == firstLetter  // only names with the same first letter in title
        .sorted  $0.nameTitle < $1.nameTitle  // sort them

    使用它们
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? 
    return sortedFirstLetters[section]


func sectionIndexTitles(for tableView: UITableView) -> [String]? 
    return sortedFirstLetters


func numberOfSections(in tableView: UITableView) -> Int 
    return sections.count // or sortedFirstLetters.count


func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    return sections[section].count


func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    let name = sections[indexPath.section][indexPath.row]
    ...

编辑 - 完整示例:

class Name 
    let nameTitle: String
    let nameDetail: String

    init(nameTitle: String, nameDetail: String) 
        self.nameTitle = nameTitle
        self.nameDetail = nameDetail
    

    var titleFirstLetter: String 
        return String(self.nameTitle[self.nameTitle.startIndex]).uppercased()
    


class ViewController : UIViewController, UITableViewDelegate, UITableViewDataSource 
    @IBOutlet weak var tableView: UITableView?

    var names: [Name] = []

    var sortedFirstLetters: [String] = []
    var sections: [[Name]] = [[]]

    override func viewDidLoad() 
        super.viewDidLoad()

        let cell001 = Name(nameTitle: "Acker", nameDetail: "Details for Acker are listed here.")
        names.append (cell001)

        let cell002 = Name(nameTitle: "Baker", nameDetail: "Details for Baker are listed here.")
        names.append (cell002)

        let cell003 = Name(nameTitle: "Caker" , nameDetail: "Details for Caker are listed here.")
        names.append (cell003)

        let cell004 = Name(nameTitle: "Dacker", nameDetail: "Details for Dacker are listed here.")
        names.append (cell004)

        let cell005 = Name(nameTitle: "Ecker", nameDetail: "Details for Ecker are listed here.")
        names.append (cell005)

        let cell006 = Name(nameTitle: "Facker", nameDetail: "Details for Facker are listed here.")
        names.append (cell006)

        let firstLetters = names.map  $0.titleFirstLetter 
        let uniqueFirstLetters = Array(Set(firstLetters))

        sortedFirstLetters = uniqueFirstLetters.sorted()
        sections = sortedFirstLetters.map  firstLetter in
            return names
                .filter  $0.titleFirstLetter == firstLetter 
                .sorted  $0.nameTitle < $1.nameTitle 
        
    

    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? 
        return sortedFirstLetters[section]
    

    func sectionIndexTitles(for tableView: UITableView) -> [String]? 
        return sortedFirstLetters
    

    func numberOfSections(in tableView: UITableView) -> Int 
        return sections.count
    

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        return sections[section].count
    

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        let name = sections[indexPath.section][indexPath.row]

        let cell = UITableViewCell(style: .subtitle, reuseIdentifier: nil)
        cell.textLabel?.text = name.nameTitle
        cell.detailTextLabel?.text = name.nameDetail

        return cell
    

【讨论】:

感谢您的解释。不幸的是,当我使用您的建议时,没有数据流到 tableView 并且它出现空白。我已经搬了东西,还没有想出解决办法。我错过了什么吗?也许我将代码放在错误的位置?再次感谢! @dalex 只需使用打印并查看您的数据包含的内容,如果从numberOfRowsInSectionnumberOfSections 返回正确的值 我做了一个打印语句,它在控制台打印了一个空的 [ ]。 @dalex 如果您的原始数组不为空,我添加的代码无法生成空数据。 我一定是在模型类或其他地方做错了什么。我想我不明白数组是如何创建的。据我了解,在调用 name.append 时,在 viewDidLoad(在我的 TableOfContentsVC 中)中创建之前,该数组是空的;这是不正确的吗?我创建了扩展并插入了符合 UIViewController 协议的代码,但数据没有流入数组以供代码查看、显示和排序。我需要更新 cellForRowAt indexPath 中的内容吗?我很困惑...非常感谢您的帮助!

以上是关于如何使用自定义模型类按部分按字母顺序对 tableView 中的数据进行排序?的主要内容,如果未能解决你的问题,请参考以下文章

在自定义 foreach 循环中按字母顺序对结果进行排序

如何按字母顺序对项目进行排序?

如何按字母顺序对 QTableView 中的项目进行排序

使用自定义顺序的 XML 排序 [重复]

如何将 NSArray 拆分为按字母顺序排列的部分以与索引表视图一起使用

使用 NSFetchRequest 按日期和单元格按时区字母顺序对部分进行排序