1

Here is the output of "print(dict)"...

["2018-10-17 11:19:51": {
firstname = Brooke;
id = 40vI7hApqkfX75SWsqIR6cdt7xV2;
lastname = Alvarez;
message = hshahyzhshbsbvash;
username = poiii;
}]
["2018-10-17 11:20:31": {
firstname = Trevor;
id = 40vI7hApqkfX75SWsqIR6cdt7xV2;
lastname = Bellai;
message = hey;
username = br9n;
}]
["2018-10-17 11:20:44": {
firstname = Amy;
id = 40vI7hApqkfX75SWsqIR6cdt7xV2;
lastname = Ikk;
message = hey;
username = nine9;
}]

My code...

Database.database().reference().child("recent-msgs").child(uid!).observe(.childAdded) { (snapshot: DataSnapshot) in
    if let dict = snapshot.value as? [String: Any] {
        print(dict)

        // Store data in user.swift model
        let firstnameData = dict[0]["firstname"] as! String
        let idData = dict["id"] as! String
        let lastnameData = dict["lastname"] as! String
        let messageData = dict["message"] as! String
        let usernameData = dict["username"] as! String
        let rankData = dict["rank"] as! String
        let propicrefData = dict["propicref"] as! String
        let convoinfo = RecentConvo(firstnameString: firstnameData, idString: idData, lastnameString: lastnameData, messageString: messageData, usernameString: usernameData, rankString: rankData, propicrefString: propicrefData)
        self.recentconvos.append(convoinfo)
        print(self.recentconvos)
        self.tableView.reloadData()
    }
}

I'm trying to retrieve the dictionary within the first dictionary which is the value to the key which is the date associate with it. For example: 2018-10-17 11:19:51. However I cannot use this exact string to call it because I must do this without the knowledge of that string.

I tried this:

let firstnameData = dict[0]["firstname"] as! String

But it returns an error:

Cannot subscript a value of type '[String : Any]' with an index of type 'Int'

Haha
  • 278
  • 2
  • 10
  • you can get keys from a dictionary with `dict.allkeys` which gives you an array. After that you can iterate through your `array` and use those `keys` (items within the array) for your inner `dictionary` – lionserdar Oct 17 '18 at 18:36
  • In the output of the print statement that you have shared, are you sure that no parts of the same has been trimmed out (like any commas)? The output looks odd for a dictionary or an array. – D V Oct 17 '18 at 19:45

2 Answers2

0

The error noted above is showing up because you were trying to access the element at a certain position (0) from the dictionary. Dictionaries are not ordered lists, and hence won't have a fixed order of elements to be accessed.

The logged dictionary doesn't really look like a dictionary. Assuming that it is a dictionary, and its keys are the date strings, you can use the following code snippet to parse the dictionary.

class RecentConversation {
    var id: String?
    var firstName: String?
    var lastName: String?
    var message: String?
    var username: String?
    var rank: String?
    var propicref: String?

    init?(dictionary: [String: Any]?) {
        guard let dict = dictionary else {
            // Return nil in case the dictionary passed on is nil
            return nil
        }
        id = dict["id"] as? String
        firstName = dict["firstname"] as? String
        lastName = dict["lastname"] as? String
        message = dict["message"] as? String
        username = dict["username"] as? String
        rank = dict["rank"] as? String
        propicref = dict["propicref"] as? String
    }
}

Usage:

let dateStrings = dict.keys.sorted {
    // Sort in chronological order (based on the date string; if you need to sort based on the proper date,
    // convert the date string to Date object and compare the same).
    //
    // Swap the line to $0 > $1 to sort the items reverse chronologically.
    return $0 < $1
}

var conversations: [RecentConversation] = []
for date in dateStrings {
    if let conversation = RecentConversation(dictionary: (dict[date] as? [String: Any])) {
        conversations.append(conversation)
    }
}
D V
  • 348
  • 2
  • 10
  • The sample code that was added here actually iterates through all of your keys, and uses the same for parsing your model (The answer you posted looks to be only a different way of writing the code for the same). Regarding converting the date string to Date object: https://stackoverflow.com/a/41435997/3183872 – D V Oct 18 '18 at 05:23
0

You were all very helpful, so I would like to start off by saying thank you. I went ahead and applied the method that lionserdar explained. (.allKeys)

// Fetch Recent Messages
func fetchRecentMsgs() {
    // Direct to database child
    Database.database().reference().child("recent-msgs").child(uid!).observe(.childAdded) { (snapshot: DataSnapshot) in
        if let dict = snapshot.value as? NSDictionary {
            print(dict)
            print(dict.allKeys)
            let keys = dict.allKeys
            for key in keys {
                print(key)
                if let nestedDict = dict[key] as? [String: Any] {
                    print(nestedDict)
                    let firstnameData = nestedDict["firstname"] as! String
                    let idData = nestedDict["id"] as! String
                    let lastnameData = nestedDict["lastname"] as! String
                    let messageData = nestedDict["message"] as! String
                    let usernameData = nestedDict["username"] as! String

Worked for me so I hope this will help others too!

Haha
  • 278
  • 2
  • 10