Reputation: 3255
MFSAPIManager().registerNewUser(userFirstName!, lastName: userLastName!, userTypeId: 1, email: userEmail!, password: userPassword!, completionHandler: { (response) in
guard response.error == nil else {
if let error = response.error {
print(error)
}
dispatch_async(GlobalMainQueue) {
self.displayAlertViewController(title: "Error", message: "Der Benutzer konnte nicht registriert werden")
}
return
}
if let serverResponse = response.value as? Dictionary<String,AnyObject> {
let newUserReference = serverResponse["data"]!["userReference"]
if (newUserReference != nil) {
self.currentPLISTData["userReference"] = newUserReference
dispatch_async(GlobalMainQueue) {
var myAlert = UIAlertController(title: "Alert", message: "Registrierung erfolgreich", preferredStyle: UIAlertControllerStyle.Alert)
let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: { (action) in
self.dismissViewControllerAnimated(true, completion: nil)
})
myAlert.addAction(okAction)
self.presentViewController(myAlert, animated: true, completion: nil)
}
}
}
})
I get an error message that I need to change:
let newUserReference = serverResponse["data"]["userReference"]
to
let newUserReference = serverResponse["data"]!["userReference"]
so unwrapping the ["data"]
component. I am confused why this is the case?
Upvotes: 3
Views: 48
Reputation:
Accessing a Dictionary<Key,Value>
by subscript returns a Value?
. This is because the key-value pair you are looking for might not be in the dictionary. Thus it returns an optional, set if it finds the key, unset if it doesn't.
I would handle it this way, using optional chaining:
if let serverResponse = response.value as? Dictionary<String,AnyObject>,
newUserReference = serverResponse["data"]?["userReference"] {
...
}
By combining all the if..let
statements into one you reduce the 'pyramid of doom'.
Eric D makes a good point that you should test the type of the first subscript, I would do it like this:
if let serverResponse = response.value as? Dictionary<String,AnyObject>,
data = serverResponse["data"] as? [String:AnyObject],
newUserReference = data["userReference"] {
...
}
Upvotes: 1
Reputation: 70098
A Swift dictionary always returns an Optional.
It means that to be able to subscript serverResponse["data"]
with ["userReference"]
you first have to unwrap serverResponse["data"]
.
It can be done unsafely, like in your example, or safely with something like if let
:
if let data = serverResponse["data"] {
let newUserReference = data["userReference"]
}
Also note that the compiler might not now the type of serverResponse["data"]
so you may have to downcast it for being able to subscript to it, for example:
if let data = serverResponse["data"] as? [String:AnyObject] {
let newUserReference = data["userReference"]
}
Upvotes: 4