如何使用自定义模型类按部分按字母顺序对 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 只需使用打印并查看您的数据包含的内容,如果从numberOfRowsInSection
和numberOfSections
返回正确的值
我做了一个打印语句,它在控制台打印了一个空的 [ ]。
@dalex 如果您的原始数组不为空,我添加的代码无法生成空数据。
我一定是在模型类或其他地方做错了什么。我想我不明白数组是如何创建的。据我了解,在调用 name.append 时,在 viewDidLoad(在我的 TableOfContentsVC 中)中创建之前,该数组是空的;这是不正确的吗?我创建了扩展并插入了符合 UIViewController 协议的代码,但数据没有流入数组以供代码查看、显示和排序。我需要更新 cellForRowAt indexPath 中的内容吗?我很困惑...非常感谢您的帮助!以上是关于如何使用自定义模型类按部分按字母顺序对 tableView 中的数据进行排序?的主要内容,如果未能解决你的问题,请参考以下文章