0

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)
Fatih Lale
  • 51
  • 1
  • 8

2 Answers2

1

As you have discovered jsonMessage is not accessible from where you are trying to access it.

This is because of a few reasons:

  1. 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

  2. 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)
    }
}    
Scriptable
  • 19,402
  • 5
  • 56
  • 72
0

First of all, you are doing a request that's asynchronous. The jsonmessage variable is set once you get the response. But you create the UIAlertController before this happens. I'm guessing you wish to display the alert once you get a response?

Also, you can't access the jsonmessage variable outside of its scope. To fix this, move var jsonmessage : String! so that it belongs to the same scope as the UIAlertController.

You should be able to move your alert into the do catch statement, but you have to make sure that the alert is displayed on the main thread.

rodskagg
  • 3,827
  • 4
  • 27
  • 46