Code from @Sh_Khan
if let code = response.dict?["result"] as? [String : Any] {
//You're using "as?" which means you're casting as an optional type.
//One simple solution to this is here where it's unwrapped using "if let"
if let userImages = code["user_images"] as? [[String : Any]] {
// [String:Any] is a Dictionary
// [[String:Any]] is an Array of Dictionary
for item in userImages {
print(item["image_title"])
}
} else {
// We didn't unwrap this safely at all, do something else.
}
Let's dive into this a little bit. This structure is a JSON Object
{
"id": 113,
"user_id": "160",
"image": "1617349564.jpg",
"image_title": "33"
}
But it's only a JSON object when it stands alone. Adding a key, or in this example user_images makes it a dictionary. Notice that the [ is not wrapped around it. Meaning it's a standalone dictionary. If this was your object, and this alone, your original code would work, but you're dealing with an Array of Dictionaries.
"user_images":
{
"id": 113,
"user_id": "160",
"image": "1617349564.jpg",
"image_title": "33"
}
This line of code essentially means that you're expecting to get back that Array of Dictionary. Bear in mind, each value for the dictionary is not an array value, which is why you don't see something like this [[[String: Any]]] because the data isn't nested like that.
if let userImages = code["user_images"] as? [[String : Any]]
What's this about optionals?
An optional is basically a nil possible value that can be returned. Typically when working with JSON you cannot guarantee that you'll always receive a value for a given key. It's even possible for a key value pair to be completely missing. If that were to happen you'd end up with a crash, because it's not handled. Here are the most common ways to handle Optionals
var someString: String? //This is the optional one
var someOtherString = "Hello, World!" //Non-optional
if let unwrappedString1 = someString {
//This code will never be reached
} else {
//This code will, because it can't be unwrapped.
}
guard let unwrappedString2 = someString else {
//This code block will run
return //Could also be continue, break, or return someValue
}
//The code will never make it here.
print(someOtherString)
Furthermore, you can work with optionals by chain unwrapping them which is a nifty feature.
var someString: String?
var someInt: Int?
var someBool: Bool?
someString = "Hello, World!"
//someString is not nil, but an important distinction to make, if any
//fail, ALL fail.
if let safeString = someString,
let safeInt = someInt,
let safeBool = someBool {
//If the values are unwrapped safely, they will be accessible here.
//In this case, they are nil, so this block will never be hit.
//I make this point because of scope, the guard statement saves you from the
//scoping issue present in if let unwrapping.
print(safeString)
print(safeInt)
print(safeBool)
}
guard let safeString = someString,
let safeInt = someInt,
let safeBool = someBool {
//This will be hit if a value is null
return
}
//However notice the scope is available outside of the guard statement,
//meaning you can safely use the values now without them being contained
//to an if statement. Despite this example, they would never be hit.
print(safeString)
print(safeInt)
print(safeBool)
Codables. If you want to get it from here, you can useuserImages[0].image_titleto get the first one and you can use a loop to get all of them and putuserImagesinif let userImages = code["user_images] as? [String: [String:Any]].[]and dictionary{}. The value foruser_imagesis clearly an array but you treat it as dictionary.image_titlehow?