简体   繁体   中英

Swift 3 - Sorting array/dictionary: '(AnyObject)' is not a subtype of 'NSString'

this code is a glossary for abbreviations (Table View) sorted in alphabetical order and worked fine with Swift 2.2. But after conversion to Swift 3 there is an error '(AnyObject)' is not a subtype of 'NSString' at this line:

array_index = dict_list.allKeys.sorted { ($0 as AnyObject).localizedCaseInsensitiveCompare($1 as! String) == ComparisonResult.orderedAscending }

The code looks like this:

import UIKit

class GlosTableViewController: UITableViewController {

var array_index:NSArray = []

var total_index: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"]

var dict_list:NSDictionary = [
    "A" : ["AA1", "AA2"],
    "C" : ["CA1", "CB2", "CB4"],
    "D" : ["D12", "D13"],
    "E" : ["EA1", "EI1", "EL1", "EL2", "EQ1", "E12"],
    "F" : ["F33"],
    "H" : ["H11", "H14"],
    "I" : ["IM3", "IM5"],
    "L" : ["LH1"],
    "M" : ["M99"],
    "N" : ["NE1", "NE2", "NE3", "NE4"],
    "P" : ["PE1", "PE2", "PE3", "PE4", "PE5"],
    "Q" : ["QT2"],
    "R" : ["RC2", "RC5", "RC7",
    "T" : ["TI2"],
]

var dict_list1:NSDictionary = [
    "AA1" : "Dictionary text for item",
    "AA2" : "Dictionary text for item",
    "CA1" : "Dictionary text for item",
    "CB2" : "Dictionary text for item",
    "CB4" : "Dictionary text for item",
    "D12." : "Dictionary text for item",
    "D13" : "Dictionary text for item",
    "EA1" : "Dictionary text for item",
    "EI1" : "Dictionary text for item",
    "EL1" : "Dictionary text for item",
    "EL2" : "Dictionary text for item",
    "EQ1" : "Dictionary text for item",
    "E12" : "Dictionary text for item",
    "F33" : "Dictionary text for item",
    "H11" : "Dictionary text for item",
    "H14" : "Dictionary text for item",
    "IM3" : "Dictionary text for item",
    "IM5" : "Dictionary text for item",
    "LH1" : "Dictionary text for item",
    "M99" : "Dictionary text for item",
    "NE1" : "Dictionary text for item",
    "NE2" : "Dictionary text for item",
    "NE3" : "Dictionary text for item",
    "NE4" : "Dictionary text for item",
    "PE1" : "Dictionary text for item",
    "PE2" : "Dictionary text for item",
    "PE3" : "Dictionary text for item",
    "PE4" : "Dictionary text for item",
    "PE5" : "Dictionary text for item",
    "QT2" : "Dictionary text for item",
    "RC2" : "Dictionary text for item",
    "RC5" : "Dictionary text for item",
    "RC7" : "Dictionary text for item",
    "TI2" : "Dictionary text for item"
]

override func viewDidLoad() {
    super.viewDidLoad()

    array_index = dict_list.allKeys.sorted { ($0 as AnyObject).localizedCaseInsensitiveCompare($1 as! String) == ComparisonResult.orderedAscending }

}
    override func numberOfSections(in tableView: UITableView) -> Int {
    // #warning Incomplete implementation, return the number of sections
    return array_index.count
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    // #warning Incomplete implementation, return the number of rows
    let sectionTitle = array_index.object(at: section)
    as! String
    let sectionAnimals = dict_list.object(forKey: sectionTitle) as! NSArray
    return sectionAnimals.count
}

override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return 80
}

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

override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    return array_index.object(at: section) as? String
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell_Glos", for: indexPath) as! GlosTableViewCell
    let sectionTitle = array_index.object(at: indexPath.section) as! String
    let sectionAnimals = dict_list.object(forKey: sectionTitle) as! NSArray
    let animal = sectionAnimals.object(at: indexPath.row) as! String
    cell.label_title.text = animal
    cell.label_subtitle.text = dict_list1.object(forKey: animal) as? String

    return cell
}
}

I did not found a solution in the forum. Can someone help me on this?

Please change

array_index = dict_list.allKeys.sorted { ($0 as AnyObject).localizedCaseInsensitiveCompare($1 as! String) == ComparisonResult.orderedAscending }

To

 array_index = dict_list.allKeys.sorted { $0.localizedCaseInsensitiveCompare($1 as! String) == ComparisonResult.orderedAscending }

The short solution would be to to replace var array_index: NSArray = [] with var array_index: [Any] = [] .

The nicer way would be to get rid of NSArray and NSDictionary and replace them with Swift Arrays and Dictionaries with beautiful types:

import UIKit

class GlosTableViewController: UITableViewController {

    var array_index: [String] = []

    var total_index: [String] = ["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 dict_list: [String: [String]] = [
        "A" : ["AA1", "AA2"],
        "C" : ["CA1", "CB2", "CB4"],
        "D" : ["D12", "D13"],
        "E" : ["EA1", "EI1", "EL1", "EL2", "EQ1", "E12"],
        "F" : ["F33"],
        "H" : ["H11", "H14"],
        "I" : ["IM3", "IM5"],
        "L" : ["LH1"],
        "M" : ["M99"],
        "N" : ["NE1", "NE2", "NE3", "NE4"],
        "P" : ["PE1", "PE2", "PE3", "PE4", "PE5"],
        "Q" : ["QT2"],
        "R" : ["RC2", "RC5", "RC7"],
        "T" : ["TI2"]
    ]

    var dict_list1: [String: String] = [
        "AA1" : "Dictionary text for item",
        "AA2" : "Dictionary text for item",
        "CA1" : "Dictionary text for item",
        "CB2" : "Dictionary text for item",
        "CB4" : "Dictionary text for item",
        "D12." : "Dictionary text for item",
        "D13" : "Dictionary text for item",
        "EA1" : "Dictionary text for item",
        "EI1" : "Dictionary text for item",
        "EL1" : "Dictionary text for item",
        "EL2" : "Dictionary text for item",
        "EQ1" : "Dictionary text for item",
        "E12" : "Dictionary text for item",
        "F33" : "Dictionary text for item",
        "H11" : "Dictionary text for item",
        "H14" : "Dictionary text for item",
        "IM3" : "Dictionary text for item",
        "IM5" : "Dictionary text for item",
        "LH1" : "Dictionary text for item",
        "M99" : "Dictionary text for item",
        "NE1" : "Dictionary text for item",
        "NE2" : "Dictionary text for item",
        "NE3" : "Dictionary text for item",
        "NE4" : "Dictionary text for item",
        "PE1" : "Dictionary text for item",
        "PE2" : "Dictionary text for item",
        "PE3" : "Dictionary text for item",
        "PE4" : "Dictionary text for item",
        "PE5" : "Dictionary text for item",
        "QT2" : "Dictionary text for item",
        "RC2" : "Dictionary text for item",
        "RC5" : "Dictionary text for item",
        "RC7" : "Dictionary text for item",
        "TI2" : "Dictionary text for item"
    ]

    override func viewDidLoad() {
        super.viewDidLoad()

        self.array_index = dict_list.keys.sorted {
            $0.localizedCaseInsensitiveCompare($1) == .orderedAscending
        }
    }

    override func numberOfSections(in tableView: UITableView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        return array_index.count
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of rows
        let sectionTitle = array_index[section]
        let sectionAnimals = dict_list[sectionTitle]
        return sectionAnimals?.count ?? 0
    }

    override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 80
    }

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

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

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell_Glos", for: indexPath) as! GlosTableViewCell
        let sectionTitle = array_index[indexPath.section]
        let sectionAnimals = dict_list[sectionTitle]
        let animal = sectionAnimals[indexPath.row]
        cell.label_title.text = animal
        cell.label_subtitle.text = dict_list1[animal]

        return cell
    }
}

Do it the Swift way

var array_index = [String]()

var dict_list = [
  "A" : ["AA1", "AA2"],
  "C" : ["CA1", "CB2", "CB4"],
  "D" : ["D12", "D13"],
  ...
]


array_index = Array(dict_list.keys).sorted()

Notes:

  • Do not use NSArray / NSDictionary is Swift unless you have no choice.
  • Do not annotate types in Swift unless the compiler tells you

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM