web-dev-qa-db-fra.com

Sections alphabétiques dans la vue tableau en swift

J'ai une liste de noms triés par ordre alphabétique et je souhaite maintenant les afficher sous forme de tableau. J'ai du mal à regrouper ces noms pour chaque lettre.

Mon code ressemble à ceci:

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
}

et tout fonctionne plutôt bien sauf pour le regroupement qui fait que ma vue de table se termine comme ceci:

enter image description here

Je sais donc que vous devriez pouvoir utiliser la fonction filtrée dans un tableau, mais je n'ai pas compris comment l'implémenter.

Toute suggestion sur la façon de procéder serait appréciée.

15
martin

Vous pouvez mettre vos tableaux avec des noms dans un dictionnaire avec des lettres.

Par exemple 

var names = ["a": ["and", "array"], "b": ["bit", "boring"]]; // dictionary with arrays setted for letter keys

alors vous devez accéder aux valeurs de votre dictionnaire de la manière suivante

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
}
0
Sergey Pekar

Voici comment j'ai récemment implémenté la liste triée dans une tableView dans Swift par programme, 

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) { $0.0 < $1.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
    }


}
9
Rao

Téléchargez le fichier Json CountryList et mettez de côté votre projet

https://Gist.github.com/keeguon/2310008

   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
}
3
Gami Nilesh

Dans Swift 4 Dictionary (grouping: by :) a été introduit pour grouper une séquence dans un dictionnaire par un prédicat arbitraire.

Cet exemple mappe le dictionnaire groupé sur une structure personnalisée 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($0.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: $0, names: groupedDictionary[$0]!.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 numberOfSectionsInTableView(tableView: UITableView) -> Int{
    return sections.count
}

func sectionIndexTitles(for tableView: UITableView) -> [String]? {
    return sections.map{$0.letter}
}

func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    return sections[section].letter
}
3
vadian

Dans le cas où votre tableau de données n'est pas prédéfini, voici un moyen d'obtenir le même résultat.

Disons que notre classe est ViewController.

class ViewController: UIViewController {

     var contactDictionary = [String: [TTContact]]() //TTContact is a model, it has firstName and lastName properties
     var keys = [String]()
     var alphabets = (97...122).map { "\(Character(UnicodeScalar.init($0)))" }.map { $0.uppercased() } //Populating alphabets
     ... // other properties


    override func viewDidLoad() {
        super.viewDidLoad()
        //set delegate and register cell for your tableView
        self.setContacts()
    }

    private func self.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: [TTContact]]() //A temporary array
         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
        }

        return UITableViewCell()
    }

    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]
    }

}
0
Gaurav Chandarana