I am developing an application that json parse. I'm using the AlertView for json messages. But I can not access the jsonmessage variable in the AlertView. if I put the AlertView in DO I get this error: "libc++abi.dylib: terminating with uncaught exception of type NSException (lldb)" Sorry for my bad English. This is my code:
request.httpBody = postParameters.data(using: String.Encoding.utf8)
let task = URLSession.shared.dataTask(with:request as URLRequest){
data, response, error in
if error != nil{
print("error is \(String(describing: error))")
return;
}
do {
let myJSON = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary
if let parseJSON = myJSON {
var jsonmessage : String!
jsonmessage = parseJSON["message"] as! String?
print(jsonmessage)
}
} catch {
}
}
task.resume()
let alert = UIAlertController(title: "Alert", message: jsonmessage /*not accessible*/ , preferredStyle: .alert)
alert.addAction(UIAlertAction(title:"Ok", style:UIAlertActionStyle.default, handler:{ (UIAlertAction) in
_ = self.navigationController?.popToRootViewController(animated: true)
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "load"), object: nil)
}))
self.present(alert, animated: true, completion: nil)
As you have discovered jsonMessage is not accessible from where you are trying to access it.
This is because of a few reasons:
The request is an asynchronous task that runs in the background and takes some time to complete. So the alert view code actually runs before the jsonMessage is returned
The variable jsonMessage is also out of scope where you are trying to call it.
To help explain:
let task = URLSession.shared.dataTask(with:request as URLRequest){
data, response, error in
let fakeMessage = "hi"
// data, response, error and fakeMessage only exist here upto the closing bracket.
}
task.resume()
// fakeMessage doesn't exist here at all.
To resolve your issue you can either present your alert from within the closure (where I have put fakeMessage) or you se a completionHandler to return jsonMessage when it is ready and then show the alert.
Method 1
let task = URLSession.shared.dataTask(with:request as URLRequest){
data, response, error in
if error != nil{
print("error is \(String(describing: error))")
return;
}
do {
let myJSON = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary
if let parseJSON = myJSON {
var jsonmessage : String!
jsonmessage = parseJSON["message"] as! String?
DispatchQueue.main.async {
// some helper function to show a basic alert
self.presentAlert(title: "Response", message: jsonMessage)
}
}
} catch {
}
}
task.resume()
Method 2
func fetchSomething(completion: @escaping (String -> Void)?) {
// setup request
let task = URLSession.shared.dataTask(with:request as URLRequest){
data, response, error in
let fakeMessage = "hi"
completion(fakeMessage)
}
task.resume()
}
then you can use it this way
self.fetchSomething { response in
DispatchQueue.main.async {
// some helper function to show a basic alert
self.presentAlert(title: "Response", message: jsonMessage)
}
}