-3

I`m trying to make a http-get-request function but it still now working. https://i.stack.imgur.com/8hge2.png

But if I do like there, function returns an empty result

https://i.stack.imgur.com/CTCt4.png

What`s wrong with that?

SwiftStudier
  • 2,272
  • 5
  • 21
  • 43

2 Answers2

1

first you are using a closure, look at the meaning of this:

 {()->void in 
   return // the closure returns a void
 }

you are using async request, so you need to do a call back function.

if you are familiar with javascript, I think this is a great explanation about how async works.

Community
  • 1
  • 1
Daniel Krom
  • 9,751
  • 3
  • 43
  • 44
1

The function you are calling has the following prototype :

func dataTaskWithRequest(
    _ request: NSURLRequest, 
    completionHandler completionHandler: (NSData?, NSURLResponse?, NSError?) -> Void
) -> NSURLSessionDataTask?

It means the completionHandler closure don't have to return something. So it's normal it's saying you that String is not convertible to Void.

What you are expecting is calling a synchronous method expecting it to return when the asynchronous call inside is finished. It's possible but I don't think that's the way you want to do it (it might block the UI).

If you want this code to run as I think you expect it to work you need to change httpGet: to be able to pass a completionHandler too that will be called by the completionHandler of dataTaskWithRequest.

Like this :

func httpGet(url: String, completion: String -> Void) {
    var googleUrl = NSURL(string: url)
    var request = NSMutableURLRequest(URL: googleUrl!)

    request.HTTPMethod = "GET"
    request.addValue("text/html", forHTTPHeaderField: "Content-Type")

    var session = NSURLSession.sharedSession()

    let task = session.dataTaskWithRequest(request, completionHandler: { data, response, error in
        if error != nil {
            println(error.localizedDescription)
        }

        completion(NSString(data: data, encoding: NSUTF8StringEncoding) as! String)
    })

    task.resume()
}

Please note this code is not safe at all (force unwrapping and too few checks) but it sums up how you should structure your code.

To use it somewhere you can do as follows :

Let's imagine you have a label Outlet.

httpGet("http://someurl.com") { result in
    label.text = result
}

The text attribute of label will be set as soon as the async call finished.

Fantattitude
  • 1,842
  • 2
  • 18
  • 34
  • thanks, and how should I use it? I`m trying to make a http-request-calling easy in syntax like response = httpGet(url) – SwiftStudier Jul 28 '15 at 12:27
  • You can't really do this. I'll show you how to use it by editing my anwser wait a sec. – Fantattitude Jul 28 '15 at 12:29
  • I see. Last question: I declared a var res:String="" at the top of ViewController.swift. Then the httpGet-func going and then - viewDidload action where I`m using it httpGet2("http://my1test.ru/applejesus.php?task=getCategoryCount") { result in self.res = result } So then I`m using println(res) and it`s empty. But if I print result - I see the answer I need ("12"). What`s wrong am I doing? – SwiftStudier Jul 28 '15 at 12:38
  • @SwiftStudier You should really learn more about how Async work it can be quite hard to understand if you never worked with it. You're doing it the right way. If you need the value inside `viewDidLoad` just put the code inside the closure. If you need it later you can store it like you did but it will be available only when the asynchronous call as ended. – Fantattitude Jul 28 '15 at 12:46