0

I want my function openDoor to return true, if the API call has given us doorStatus "OPENED" However, I run into a problem, where this function returns before the API call has been made, making it return false every time, because it has been initialised so. My question is how do I make api request first, so that I can assign doorStatusL true or false based on that API call to return it at the end?

                func openDoor(requesto: URLRequest) ->Bool {
                 var doorstatusL = false;


                func sendRequest() -> Bool {
                NSURLConnection.sendAsynchronousRequest(requesto, queue: OperationQueue.main) {(response, data, error) in

                    guard let data = data else {
                        return
                    }
                    print(String(data: data, encoding: .utf8)!)
                    do {

                        let json = try JSONDecoder().decode([WelcomeElement].self, from: data )
                        //try JSONSerialization.jsonObject(with: data!, options: [])
                        print(json[0].doorstatus)
                        if(json[0].doorstatus == "OPENED"){
                            doorstatusL = true;
                            print(doorstatusL)
                            print("assigned TRUE")
                        }
                    } catch {
                        print("Status Error during JSON serialization: \(error.localizedDescription)")
                    }
                    }
                    return true
                }
                if(sendRequest()==true){
                    print(doorstatusL)
                    print("=======+++++++")
                    return doorstatusL
                } else {
                    print("returned false at the end")
                    return false
                }  
               return true;
            }

Output from a terminal is

false
=======+++++++
[{"message":"OPEN, ENTER ","doorstatus":"OPENED"}] 
OPENED
true
assigned TRUE

Thank you

SOLVED

                        func sendRequest(requesto: URLRequest, success:Bool, completionHandler: @escaping (Bool)->Void) {
                        var doorStatusL = false

                        NSURLConnection.sendAsynchronousRequest(requesto, queue: OperationQueue.main) { (response, data, error) in
                            guard let data = data else { return }

                            do {
                                let json = try JSONDecoder().decode([WelcomeElement].self, from: data )

                                if(json[0].doorstatus == "OPENED") {
                                    doorStatusL = true
                                    completionHandler(doorStatusL)
                                }
                            } catch {
                                print("Status Error during JSON serialization: \(error.localizedDescription)")
                            }
                        }
                    }

                    let completionhandler:(Bool)->Void = { (success) in
                        if success {
                                sendNotifications()
                        }
                    }

                    sendRequest(requesto: request2, success: true, completionHandler: completionhandler)

2 Answers2

2
func openDoor(requesto: URLRequest,completionHandler:@escaping (Bool) -> ()) {
    func sendRequest() -> Bool {
            NSURLConnection.sendAsynchronousRequest(requesto, queue: OperationQueue.main) {(response, data, error) in

                guard let data = data else {
                    return
                }
                print(String(data: data, encoding: .utf8)!)
                do {

                    let json = try JSONDecoder().decode([WelcomeElement].self, from: data )
                    //try JSONSerialization.jsonObject(with: data!, options: [])
                    print(json[0].doorstatus)
                    if(json[0].doorstatus == "OPENED"){
                        doorstatusL = true;
                        print(doorstatusL)
                        print("assigned TRUE")
                    }
                } catch {
                    print("Status Error during JSON serialization: \(error.localizedDescription)")
                }
                }
                completionHandler(true)
            }
            if(sendRequest()==true){
                print(doorstatusL)
                print("=======+++++++")
                completionHandler(doorstatusL) 
            } else {
                print("returned false at the end")
                completionHandler(false)
            }  
    })
}

Usage:

openDoor() { requesto: urlHere,success in
   print(success)
}

Escaping Closure : An escaping closure is a closure that’s called after the function it was passed to returns. In other words, it outlives the function it was passed to.

Non-escaping closure : A closure that’s called within the function it was passed into, i.e. before it returns.

You can read more about it in this question: Swift @escaping and Completion Handler

Ben Shabat
  • 388
  • 4
  • 17
  • Thank you for such a detailed answer @ben. I don't quite understand the usage part. Why are request and success in the main closure and not in the parameters of openDoor func? I tried to put them into the parameters, however still keep getting errors both ways. I am not syntactically good with swift. – Alan Kantserov Feb 19 '20 at 04:31
  • The request is the urlRequst declared in your openDoor func and the success variable is the Bool returning from the completion handler, you should name it isSuccess i guess that's a better name for this variable – Ben Shabat Feb 19 '20 at 09:29
1

Add completion handler to api call method

func sendRequest(completion:@escaping (_ response:Bool) -> Void){
   completion(true)
}

then you can call a function on completion of it

sendRequest(completion: {_ in
    yourFunction()
})
Jayesh Patel
  • 938
  • 5
  • 16