1

I'm displaying a dictionary as UITableView. I did this very easily in Objective- c . But now in swift, I cannot get values from array of dictionary. When I try to get values in the tableView:cellForRowAtIndexPath the precompiler throw error like

Cannot convert value of type "AnyObject?!" to specified type 'Array'

or like in this example below

Cannot convert value of type "AnyObject?!" with an idnex of type 'int'

var cellArray = []

override func viewDidLoad() {
    cellArray = [
        [
            "section" : "Melody",
            "rows" :
                [
                    [
                        "title" : "Wi-Fi / Pairing",
                        "icon" : "",
                        "action" : "actionConnectSpeaker"
                    ],
                    [
                        "title" : "Sound",
                        "icon" : "",
                        "action" : "actionConnectSpeaker"
                    ]
                ]
        ],

        [
            "section" : "Music",
            "rows" :
                [
                    [
                        "title" : "Add a new account",
                        "icon" : "",
                        "action" : "actionAddAccount"
                    ]
                ]
        ]
    ]
}

...

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    let cell = UITableViewCell(style: UITableViewCellStyle.Value2, reuseIdentifier: nil)

    cell.textLabel?.text = cellArray[indexPath.section]["rows"][indexPath.row]["title"]


    return cell
}

I conclude we cannot do like this... I find any example. I probably not understand something about Types in Swift ...

4 Answers 4

2

In Swift you have to downcast AnyObject types if you want to call functions like objectAtIndex: or objectForKey: what subscripting actually does.

let section = cellArray[indexPath.section]
let rows = section["rows"] as! [[String:String]]
cell.textLabel?.text = rows[indexPath.row]["title"]
Sign up to request clarification or add additional context in comments.

Comments

0

Simply doing this if you're sure there's no nil value:

cell.textLabel?.text = cellArray[indexPath.section]["rows"]![indexPath.row]["title"]

1 Comment

check the answer above. Your answer answers to an other problem
0

If you want to do it safely (if any object can be nil or the other type, you should use if let:

if let dict = cellArray[indexPath.section] as? [String : AnyObject],
    rows = dict["rows"] as? [AnyObject], 
    result = rows[indexPath.row] as? [String : AnyObject],
    title = result["title"] {
    cell.textLabel?.text = title
}

Comments

0

You should generally avoid collections with elements of different types in Swift. Your section data is a dictionary, the value of "section" key is a string while the value of "rows" key is an array. Try to replace this dictionary with a tuple.

var cellArray = [(String, [[String: String]])]()

override func viewDidLoad() {
    cellArray = [
        (
            "Melody",
            [
                [
                    "title" : "Wi-Fi / Pairing",
                    "icon" : "",
                    "action" : "actionConnectSpeaker"
                ],
                [
                    "title" : "Sound",
                    "icon" : "",
                    "action" : "actionConnectSpeaker"
                ]
            ]
        ),

        (
            "Music",
            [
                [
                    "title" : "Add a new account",
                    "icon" : "",
                    "action" : "actionAddAccount"
                ]
            ]
        )
    ]
}

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    let cell = UITableViewCell(style: UITableViewCellStyle.Value2, reuseIdentifier: nil)

    cell.textLabel?.text = cellArray[indexPath.section].1[indexPath.row]["title"]

    return cell
}

This way Swift's type system can help you make sure you are using the right type, no force downcasting is needed.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.