iosuitableviewswift4xcode9swift3.2

'[NSObject]' is not convertible to '[AnyObject]'


I'm trying to create tableview where the arrays are being sorted and put in there respective sections. I followed this tutorial: http://www.yudiz.com/creating-tableview-with-section-indexes/

I managed to make the first one work where the tableview arrays are sorted even though the sections without data still appear.

The second one is about solving the problem in which the sections without data still appear which did not work for me.

Upon following the second one, I could not run it because of this error

'[MyContact]' is not convertible to '[AnyObject]'

Here is my code:

Model for contact:

class MyContact: NSObject {
    @objc var name: String!
    @objc var mobile: String!

    init(name: String, mob: String) {
        self.name = name
        self.mobile = mob
    }
}

Extension for partitioning arrays into sorted subcategories

extension UILocalizedIndexedCollation {

    func partitionObjects(array: [AnyObject], collationStringSelector: Selector) -> ([AnyObject], [String]) {
        var unsortedSections = [[AnyObject]]()

        for _ in self.sectionTitles {
            unsortedSections.append([])
        }

        for item in array {
            let index: Int = self.section(for: item, collationStringSelector: collationStringSelector)
            unsortedSections[index].append(item)
        }
        var sectionTitles = [String]()
        var sections = [AnyObject]()
        for index in 0 ..< unsortedSections.count {
            if unsortedSections[index].count > 0 {
                sectionTitles.append(self.sectionTitles[index])
                sections.append(self.sortedArray(from: unsortedSections[index], collationStringSelector: collationStringSelector) as AnyObject)
            }
        }
        return (sections, sectionTitles)
    }
}

Tuple for data source and the line which has the error

let (arrayContacts, arrayTitles) = collation.partitionObjects(array: self.myContacts, collationStringSelector: #selector(getter: MyContact.name)) as! [[MyContact]]

Solution

  • You're trying to force cast a tuple into an array of arrays.

    let (arrayContacts, arrayTitles) = collation.partitionObjects(array: self.myContacts, collationStringSelector: #selector(getter: MyContact.name))
    

    will return a tuple of type ([AnyObject], [String]).

    Also, you shouldn't be using AnyObject unless you really need something to be a class type. You can re-write like this:

    extension UILocalizedIndexedCollation {
        func partitionObjects(array: [Any], collationStringSelector: Selector) -> ([Any], [String]) {
            var unsortedSections = [[Any]](repeating: [], count: self.sectionTitles.count)
    
            for item in array {
                let index = self.section(for: item, collationStringSelector: collationStringSelector)
                unsortedSections[index].append(item)
            }
            var sectionTitles = [String]()
            var sections = [Any]()
            for index in 0..<unsortedSections.count {
                if unsortedSections[index].isEmpty == false {
                    sectionTitles.append(self.sectionTitles[index])
                    sections.append(self.sortedArray(from: unsortedSections[index], collationStringSelector: collationStringSelector))
                }
            }
            return (sections, sectionTitles)
        }
    }
    

    That way you could write MyContact as a struct and it would still work with this function.