user1510010 user1510010 - 21 days ago 5
iOS Question

Cannot subscript a value of type - Swift 3

I'm new to Swift and am trying to write an application to parse json from a webpage. However I'm getting the error
"Cannot subscript a value of type '[Dictionary]'"

How can I fix this? It occurs multiple times. Following is my code. Thanks!

func grabData(results: [Dictionary<String, Any?>]){
guard let resultList = results as? [Dictionary<String, Any?>] else { return }
for iResult in resultList {
var tempResult = SearchResult()
tempResult.studentId = self.getInt(dict: [iResult], string: "StudentId")
tempResult.LastName = self.getString(dict: [iResult], string: "LastName")
tempResult.FirstName = self.getString(dict: [iResult], string: "FirstName")
tempResult.Major = self.getString(dict: [iResult], string: "Major")
tempResult.Year = self.getString(dict: [iResult], string: "Year")
tempResult.GPA = self.getDouble(dict: [iResult], string: "GPA")
self.results.append(tempResult)
}
DispatchQueue.main.async {
self.listTableView.reloadData()
}
}

func getString(dict: [Dictionary<String, Any?>], string: String) -> String? {
if let result = dict[Dictionary<String, Any?>] as? String {
return result
}
return nil
}

func getInt(dict: [Dictionary<String, Any?>], string: String) -> Int? {
if let result = dict[string] as? Int {
return result
}
return nil
}

func getDouble(dict: [Dictionary<String, Any?>], string: String) -> Double? {
if let result = dict[string] as? Double {
return result
}
return nil
}

Answer

SearchResult.swift

struct SearchResult {
    let studentID: Int
    let lastName: String
    let firstName: String
    let major: String
    let year: String
    let gpa: Double

    init?(json: [String:AnyObject]) {
        guard let studentID = json["StudentID"] as? Int else {
            return nil
        }

        guard let lastName = json["LastName"] as? String else {
            return nil
        }

        guard let firstName = json["FirstName"] as? String else {
            return nil
        }

        guard let major = json["Major"] as? String else {
            return nil
        }

        guard let year = json["Year"] as? String else {
            return nil
        }

        guard let gpa = json["GPA"] as? Double else {
            return nil
        }

        self.studentID = studentID
        self.lastName = lastName
        self.firstName = firstName
        self.major = major
        self.year = year
        self.gpa = gpa
    }
}

ViewController.swift

func grabData(json: [String:AnyObject]) {
    guard let searchResult = SearchResult(json) else {
        return
    }

    self.results.append(searchResult)

    DispatchQueue.main.async {
        self.listTableView.reloadData()
    }
}

This post was helpful to me when I designing my model to interact with a REST API: https://developer.apple.com/swift/blog/?id=37

The structure of your JSON also makes a difference.

For example:

[
    {
        "StudentID": 12345,
        "LastName": "Smith"
    }
]

Would be represented as [[String:AnyObject]] (an array of String and AnyObject combinations)

If you have this, then you need to loop through and then parse each element individually.