Difficulty loading sections in cellForRowAt

Asked

Viewed 67 times

1

I’m having a little difficulty in implementing indexes (A through Z) in my app... See the structure below, what should I do to properly load the indexPath.section?:

struct EmployeeDetails {
    let functionary: String
    let imageFace: String
    let phone: String

    init(dictionary: [String: Any]) {
        self.functionary = (dictionary["Functionary"] as? String) ?? ""
        self.imageFace = (dictionary["ImageFace"] as? String) ?? ""
        self.phone = (dictionary["Phone"] as? String) ?? ""
    }
}
struct Employee {
    let position: String
    let name: String
    let details: [EmployeeDetails] // [String:Any]

    init(dictionary: [String: Any]) {
        self.position = (dictionary["Position"] as? String) ?? ""
        self.name = (dictionary["Name"] as? String) ?? ""

        let t = (dictionary["Details"] as? [Any]) ?? []
        self.details = t.map({EmployeeDetails(dictionary: $0 as! [String : Any])})
    }
}

struct Shared {
    static var instance = Shared()
    var employees: [Employee] = []
}

I believe the mistake is in cellForRowAt in the TableViewController:

@IBOutlet weak var searchBar: UISearchBar!

var employeesSearching = [Employee]()
var isSearching : Bool = false

let collation = UILocalizedIndexedCollation.current()
var sections: [[AnyObject]] = []
var objects: [AnyObject] = [] {
    didSet {
        let selector: Selector = #selector(getter: UIApplicationShortcutItem.localizedTitle)
        sections = Array(repeating: [], count: collation.sectionTitles.count)

        let sortedObjects = collation.sortedArray(from: objects, collationStringSelector: selector)
        for object in sortedObjects {
            let sectionNumber = collation.section(for: object, collationStringSelector: selector)
            sections[sectionNumber].append(object as AnyObject)
        }
        self.tableView.reloadData()
    }
}

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

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return isSearching ? employeesSearching.count : sections[section].count
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCell1
    let entry = isSearching ? employeesSearching[indexPath.row] : Shared.instance.employees[indexPath.row]

    //sections[indexPath.section][indexPath.row]   ??? COMO ???

    cell.nameLabel.text = entry.name
    cell.positionLabel.text = entry.position

    return cell
}

override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    return collation.sectionTitles[section]
}

override func sectionIndexTitles(for tableView: UITableView) -> [String]? {
    return collation.sectionIndexTitles
}

override func tableView(_ tableView: UITableView, sectionForSectionIndexTitle title: String, at index: Int) -> Int {
    return collation.section(forSectionIndexTitle: index)
}

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    if self.searchBar.text!.isEmpty {
        self.isSearching = false
        self.tableView.reloadData()
    } else {
        self.isSearching = true
        self.employeesSearching.removeAll(keepingCapacity: false)
        let searchText = self.searchBar.text!.lowercased()
        for employee in Shared.instance.employees {
            if employee.name.lowercased().range(of: searchText) != nil {
                self.employeesSearching.append(employee)
            }
        }
    }
        self.tableView.reloadData()
}

How do I implement sections, [indexPath.section] and [indexPath.row] in the same code line in this case?

  • 1

    exchange for let t = dictionary["Details"] as? [[String:Any]] ?? [] and pull out the force cast self.details = t.map( { EmployeeDetails(dictionary: $0) } )

  • @Leodabus The app is running, but Tableview is empty. I wouldn’t have to enter something like sections or [indexPath.section] in the cellForRowAt? If yes, as?

  • @Leodabus, any thoughts, comrade?

  • 1

    the ideal is to Voce use the Object type in your array sections instead of Anyobject to facilitate Voce access the element properties

  • @Leodabus I did it, he asks to put cell as (entry as AnyObject) and after that it shows error: Cannot assign value of type 'Cgpoint! ' to type 'String?'

  • @Leodabus, I also tried something like cell.nameLabel.text = entry[sections[indexPath.section][indexPath.row]].name, but he does not receive.

Show 1 more comment

1 answer

1


I think the ideal is that your employeesSearching is a two-dimensional array already organized by sections.

That is, the Employee that is from Section 0 will be in employeesSearching[0][i], which is from 1, will be in employeeSearching[1][i] and so on...

Take your list, go through it by organizing in a two-dimensional array and then you can, in cellForRowAt only do entry = employeesSearching[indexPath.Section][indexPath.Row].

  • I did what you suggested. But I also needed to change the Struct Shared for var employees: [[Employee]] = []. Hence I inserted [indexPath.section] in the cellForRowAt, All this became 100%!! However in func searchBar he is returning me an error that I cannot resolve -> he is saying that the type value [Employe] does not have the member name. I edited my question for you to see. The error is on the line: if employee.name.lowercased().range(of: searchText) != nil. From now on VERY MUCH thank you!

  • I’m on my cell phone and I couldn’t find the line you mentioned. But from the error message, it looks like you took Employee as if it were Employee, but it’s actually an Employee array. Check you forgot to pick up Employee by the right Section index.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.