ios 快速表格视图中的字母部分
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28087688/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Alphabetical sections in table table view in swift
提问by martin
I have a list of names sorted alphabetically, and now I want display these names in a table view. I'm struggling with grouping these names for each letter.
我有一个按字母顺序排序的名称列表,现在我想在表格视图中显示这些名称。我正在努力为每个字母对这些名称进行分组。
My code looks like this:
我的代码如下所示:
let sections:Array<AnyObject> = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]
var usernames = [String]()
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
let cellID = "cell"
let cell: UITableViewCell = self.tv.dequeueReusableCellWithIdentifier(cellID) as UITableViewCell
cell.textLabel?.text = usernames[indexPath.row]
return cell
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return usernames.count
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int{
return 26
}
func sectionIndexTitlesForTableView(tableView: UITableView) -> [AnyObject]!{
return self.sections
}
func tableView(tableView: UITableView,
sectionForSectionIndexTitle title: String,
atIndex index: Int) -> Int{
return index
}
func tableView(tableView: UITableView,
titleForHeaderInSection section: Int) -> String?{
return self.sections[section] as? String
}
and it all works pretty good except for the grouping which makes my table view end up like this:
除了分组使我的表视图最终像这样之外,一切都很好:
So I know you should be able to use the filtered function in an Array, but I did not understand how to implement it.
所以我知道你应该能够在数组中使用过滤函数,但我不明白如何实现它。
Any suggestions on how to proceed would be appreciated.
任何有关如何进行的建议将不胜感激。
采纳答案by Sergey Pekar
You can put your arrays with names into dictionary with letter keys.
您可以使用字母键将带有名称的数组放入字典中。
For example
例如
var names = ["a": ["and", "array"], "b": ["bit", "boring"]]; // dictionary with arrays setted for letter keys
then you need to access values in your dictionary in the next way
那么您需要以下一种方式访问字典中的值
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return names[usernames[section]].count; // maybe here is needed to convert result of names[...] to NSArray before you can access count property
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
let cellID = "cell"
let cell: UITableViewCell = self.tv.dequeueReusableCellWithIdentifier(cellID) as UITableViewCell
cell.textLabel?.text = names[usernames[indexPath.section]][indexPath.row]; // here you access elements in arrray which is stored in names dictionary for usernames[indexPath.section] key
return cell
}
回答by vadian
In Swift 4 Dictionary(grouping:by:)was introduced to group a sequence to a dictionary by an arbitrary predicate.
在 Swift 4 Dictionary(grouping:by:)中引入了通过任意谓词将序列分组到字典中。
This example maps the grouped dictionary to a custom struct Section
此示例将分组字典映射到自定义结构 Section
struct Section {
let letter : String
let names : [String]
}
...
let usernames = ["John", "Nancy", "James", "Jenna", "Sue", "Eric", "Sam"]
var sections = [Section]()
override func viewDidLoad() {
super.viewDidLoad()
// group the array to ["N": ["Nancy"], "S": ["Sue", "Sam"], "J": ["John", "James", "Jenna"], "E": ["Eric"]]
let groupedDictionary = Dictionary(grouping: usernames, by: {String(import UIKit
class BreedController: UITableViewController{
var breeds = ["A": ["Affenpoo", "Affenpug", "Affenshire", "Affenwich", "Afghan Collie", "Afghan Hound"], "B": ["Bagle Hound", "Boxer"]]
struct Objects {
var sectionName : String!
var sectionObjects : [String]!
}
var objectArray = [Objects]()
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
tableView.registerClass(UITableViewCell.classForCoder(), forCellReuseIdentifier: "Cell")
// SORTING [SINCE A DICTIONARY IS AN UNSORTED LIST]
var sortedBreeds = sorted(breeds) { var json = NSArray()
var arr_name = NSArray()
var arrIndexSection : NSArray = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"]
override func viewDidLoad() {
let path = Bundle.main.path(forResource: "countries", ofType: "json")
let data = NSData(contentsOfFile: path! )
json = (try! JSONSerialization.jsonObject(with: data as! Data, options: JSONSerialization.ReadingOptions.mutableContainers)) as! NSArray
arr_name = json.value(forKey: "name") as! NSArray;
tableview.reloadData()
super.viewDidLoad()
}
// Side List in tableview
public func numberOfSections(in tableView: UITableView) -> Int {
return 26
}
public func sectionIndexTitles(for tableView: UITableView) -> [String]? {
return self.arrIndexSection as? [String] //Side Section title
}
public func tableView(_ tableView: UITableView, sectionForSectionIndexTitle title: String, at index: Int) -> Int
{
return index
}
public func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return arrIndexSection.object(at: section) as? String
}
// number of rows in table view
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
let predicate = NSPredicate(format: "SELF beginswith[c] %@", arrIndexSection.object(at: section) as! CVarArg)
let arrContacts = (arr_name as NSArray).filtered(using: predicate)
return arrContacts.count;
}
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell : TableViewCell=self.tableview.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCell
let predicate = NSPredicate(format: "SELF beginswith[c] %@", arrIndexSection.object(at: indexPath.section) as! CVarArg)
let arrContacts = (arr_name as NSArray).filtered(using: predicate) as NSArray
cell.textLabel?.text = arrContacts.object(at: indexPath.row) as? String
return cell
}
.0 < .0 }
for (key, value) in sortedBreeds {
println("\(key) -> \(value)")
objectArray.append(Objects(sectionName: key, sectionObjects: value))
}
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return objectArray.count
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return objectArray[section].sectionObjects.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! UITableViewCell
// SETTING UP YOUR CELL
cell.textLabel?.text = objectArray[indexPath.section].sectionObjects[indexPath.row]
return cell
}
override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return objectArray[section].sectionName
}
}
.prefix(1))})
// get the keys and sort them
let keys = groupedDictionary.keys.sorted()
// map the sorted keys to a struct
sections = keys.map{ Section(letter: class ViewController: UIViewController {
var contactDictionary = [String: [Contact]]() //Contact is a model, it has firstName and lastName properties
var keys = [String]()
var alphabets = (97...122).map { "\(Character(UnicodeScalar.init(var nameList = ["Abc","Bbc","Cbc",......]//whatever it is
var arrNameList = [[nameList]]()
var str = String()
override func viewDidLoad() {
str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
for i : Int in 0 ..< (str.count) {
var arr = [nameList]()
for j : Int in 0 ..< nameList.count {
let name = nameList[j]
let index = str.index(str.startIndex, offsetBy: i)
let char = str[index]
if name.first == char {
arr.append(name)
}
}
arrNameList.append(arr)
}
}
func numberOfSections(in tableView: UITableView) -> Int {
return arrNameList.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection
section: Int) -> String? {
let index = str.index(str.startIndex, offsetBy: section)
let char = str[index]
return char
}
func tableView(_ tableView: UITableView, numberOfRowsInSection
section: Int) -> Int {
return arrNameList[section].count
}
func tableView(_ tableView: UITableView, heightForHeaderInSection
section: Int) -> CGFloat {
return 40
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath:
IndexPath) -> CGFloat {
return 40
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath:
IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell",
for: indexPath) as! NameListTableViewCell
let name = arrNameList[indexPath.section][indexPath.row]
cell.nameLbl.text = name
cell.selectionStyle = .none
return cell
}
)))" }.map { var frndsName = ["Vanitha","Ilakkiya","Parveen","Divya","Seetha","Madhavi","Ashwini","Sangeetha","Swathi","Don","Priyanka","Tamilselvi","Premlatha","Prashanthi","Rekha","Ajitha","Praveena","Indhusree","Nisha","Priya","Lavanya","Sandhiya","Gejalakshmi","Pavithra","Abinaya"]
let sections = ["*","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","#"]
var dividedArray:NSMutableArray = []
override func viewDidLoad() {
super.viewDidLoad()
for i in sections{
let dummyArray:NSMutableArray = []
for j in frndsName{
if i.first! == j.first! {
dummyArray.add(j)
}
}
dividedArray.add(dummyArray)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func numberOfSections(in tableView: UITableView) -> Int {
return 26
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return (dividedArray[section] as! NSMutableArray).count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell")
let dummyArray = dividedArray[indexPath.section] as! NSMutableArray
cell?.textLabel?.text = dummyArray[indexPath.row] as? String
return cell!
}
func sectionIndexTitles(for tableView: UITableView) -> [String]? {
return self.sections
}
func tableView(_ tableView: UITableView, sectionForSectionIndexTitle title: String, at index: Int) -> Int {
return index
}
internal func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return self.sections[section] as String
}
}
.uppercased() } //Populating alphabets
... // other properties
override func viewDidLoad() {
super.viewDidLoad()
//set delegate and register cell for your tableView
self.setContacts()
}
private func setContacts() {
//Loop through your array, take the firstName, and the first character of that string.
//Check the uppercase value of that character, if it's an alphabet or not, otherwise, we'd place "#" for the names starting with a number in the header.
var temp = [String: [Contact]]() //A temporary dictionary
for contact in self.contacts {
if let firstName = contact.firstName, !firstName.isEmpty { //In my case, the firstName is an optional string
let firstChar = "\(firstName.first!)".uppercased()
if alphabets.contains(firstChar) {
var array = temp[firstChar] ?? []
array.append(contact)
temp[firstChar] = array
} else {
var array = temp["#"] ?? []
array.append(contact)
temp["#"] = array
}
}
}
self.keys = Array(temp.keys).sorted() //Populating and sorting all the keys alphabetically.
for key in self.keys { self.contactDictionary[key] = temp[key] }
//reload table
}
}
extension: ViewController: UITableViewDelegate, UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return self.contactDictionary.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.contactDictionary[keys[section]]?.count ?? 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let key = self.keys[indexPath.section]
let cell: //dequeue your cell here.
if let row = self.contactDictionary[key]?[indexPath.row] {
cell.display(with: row) //Bind your cell's outlets with the properties
return cell
}
//handle error
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let key = self.keys[indexPath.section]
if let row = self.contactDictionary[key]?[indexPath.row] {
//handle selection.
}
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { //You can use viewForHeaderInSection either.
return self.keys[section]
}
}
, names: groupedDictionary[##代码##]!.sorted()) }
self.tableView.reloadData()
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellID = "cell"
let cell = tableView.dequeueReusableCell(withIdentifier: cellID, for: indexPath)
let section = sections[indexPath.section]
let username = section.names[indexPath.row]
cell.textLabel?.text = username
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return sections[section].names.count
}
func numberOfSections(in tableView: UITableView) -> Int {
return sections.count
}
func sectionIndexTitles(for tableView: UITableView) -> [String]? {
return sections.map{##代码##.letter}
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return sections[section].letter
}
回答by Rao
This is how I recently implemented sorted list in a tableView in Swift programmatically,
这就是我最近在 Swift 中以编程方式在 tableView 中实现排序列表的方式,
##代码##回答by Gami Nilesh
Download CountryList Json file and put in side your project
下载 CountryList Json 文件并将其放在您的项目中
##代码##回答by Gaurav Chandarana
In case, if your data array is not predefined, here's a way to achieve the same thing.
如果您的数据数组未预定义,这里有一种方法可以实现相同的目的。
Let's say our class is ViewController.
假设我们的类是ViewController。
##代码##