Afshin Mobayen Khiabani
Afshin Mobayen Khiabani

Reputation: 1289

Calling a func in other swift file which works with web-service returns nothing

In swift 2 When I'm communicating with a web-service and when I write these codes in button action it works fine.

let alert = UIAlertController(title: "Alert", message: "Message", preferredStyle: .Alert)

    let ok = UIAlertAction(title: "OK", style: .Default, handler: { (action) -> Void in })

    alert.addAction(ok);

    let request = NSMutableURLRequest(URL: NSURL(string: "http://www.myaddress.com/web-service/iostest.aspx")!)
    request.HTTPMethod = "POST"

    var postString = String();
    postString = "uid=1";
    request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
    let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in
        guard error == nil && data != nil else {

            alert.title="Error"
            alert.message = "Connection error"

            dispatch_async(dispatch_get_main_queue()){
                self.presentViewController(alert, animated: true, completion: nil)
            }
            return
        }

        if let httpStatus = response as? NSHTTPURLResponse where httpStatus.statusCode != 200 {
            alert.title="Error"
            alert.message = "Server error"

            dispatch_async(dispatch_get_main_queue()){
                self.presentViewController(alert, animated: true, completion: nil)
            }

        }

        let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)

        alert.title="Info"
        alert.message = responseString as? String

        dispatch_async(dispatch_get_main_queue()){
            self.presentViewController(alert, animated: true, completion: nil)
        }
    }
    task.resume()

As I said this works fine but as I want to do this from different ViewControls as well I have created a swift file which contains a struct and a static func in that struct that returns the the "responseString" so I could alert it in the view control. Something like this:

struct globalClass {

static func sendInfo(url: String, data: String) -> (answer: String, errorCode: Int32) {
    var res = String();
    var err = Int32();
    err = 0;
    let request = NSMutableURLRequest(URL: NSURL(string: url)!);
    request.HTTPMethod = "POST";
    let postString: String = data;
    request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding);
    let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in
        guard error == nil && data != nil else {
            err = 1;
            return;
        }

        if let httpStatus = response as? NSHTTPURLResponse where httpStatus.statusCode != 200 {
            err = 2;
            return;
        }

        let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding);
        res = (responseString as? String)!;
    }
    task.resume();
    return (res, err);
}

But now when I call this func from my button it shows me an empty alert very fast that it seems like it didn't get anything from web-service and didn't even try too.

I put these in the button action:

@IBAction func btnData(sender: AnyObject) {

    let y: String = "uid=1";

    let res = globalClass.sendInfo("http://www.myaddress.com/web-service/iostest.aspx", data: y);

    let alert = UIAlertController(title: "", message: "", preferredStyle: .Alert);
    let OK = UIAlertAction(title: "OK", style: .Default, handler: nil);
    alert.addAction(OK);

    if (res.errorCode==0) {
        alert.title = "Info";
        alert.message = res.answer;
    } else if (res.errorCode==1) {
        alert.title = "Error";
        alert.message = "Error connecting to server";
    } else {
        alert.title = "Error";
        alert.message = "Server returned an error";
    }

    dispatch_async(dispatch_get_main_queue()){
        self.presentViewController(alert, animated: true, completion: nil);
    };

}

Thanks for the help,

Afshin Mobayen Khiabani

Upvotes: 0

Views: 99

Answers (2)

Mtoklitz113
Mtoklitz113

Reputation: 3878

static func sendInfo(url: String, data: String, completion: (answer: String, errorCode: Int32) -> ()){
//Your code..

        let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding);
        res = (responseString as? String)!;
     completion(answer: res, errorCode: err)
    }
    task.resume()



}

Then when you call the sendInfo, call like so:

sendInfo(url: "your url", data: "your data") { (result, error) in

//you use your result and error values as u want.
}

Upvotes: 1

Nimble
Nimble

Reputation: 1017

globalClass.sendInfo uses async call - dataTaskWithRequest. The result of the request will be delivered in completion of this method. But you don't wait for that result, instead you try to use sendInfo like a sync function.

To be able to deliver the result from dataTaskWithRequest's completion, put your own completion into sendInfo and invoke this completion (closure) when the result is delivered. An example

struct GlobalClass {
    static func sendInfo(url: String, data: String, completion: (answer: String?, errorCode: Int32?) -> Void) {
        // you code here which prepares request
        let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in
            // you parse the result here
            // you deliver the result using closure
            completion(string, error)
        }
        task.resume();
    }
}

And an example of usage:

func usage() {
    GlobalClass.sendInfo("url", data: "data") { (answer, errorCode) in
        // your answer and errorCode here
        // handle the result
    }
}

Upvotes: 1

Related Questions