redoff
redoff

Reputation: 1144

Load data with NSURLSession and closure iOS

i use this function to get the link of image but i just have the variable in the initialization.

func getLinkImage(link_news: String, separator: String) -> String {
    let url = NSURL(string: link_news)
    var link_image_news = "http://www.website.com"
    let task = NSURLSession.sharedSession().dataTaskWithURL(url!) { (data, response, error) -> Void in
        if error == nil {
            let urlContent = NSString(data: data!, encoding: NSUTF8StringEncoding)
            //print(urlContent)
            let urlContentArray = urlContent?.componentsSeparatedByString(separator)
            // search link's image
                print("----------Link's Image----------")
                var image_news = urlContentArray?[1].componentsSeparatedByString("<img alt=")
                image_news = image_news?[1].componentsSeparatedByString("src=")
                image_news = image_news?[1].componentsSeparatedByString("\"")
                link_image_news = "http://www.website.com" + image_news![1]
                print("the link of image is : "+link_image_news)
            // end of search link's image
        }
        else {
            print("Error in the Image News load from Website")
            print(url!)
        }
    }
    task.resume()
    return link_image_news
}

when i call the function, i have only the initialization value (link_image_news = http://www.website.com), after many seconds i have the print with right value (the link of image).

i think it's issue with response time of server. how can i solve this ? i found some stuffs with closure (completion) but i dont really understand how it's works, im new in Swift

Upvotes: 0

Views: 694

Answers (1)

Duncan C
Duncan C

Reputation: 131461

Here's the deal:

An NSURLSession "task" takes a block of code that it calls once the response from the server has been completely received.

When you call task.resume() that call returns immediately, before iOS has even begun sending the request to the remote server. What you need to do is to rewrite your getLinkImage function to not return a value, and to take a completion block as a parameter.

Make that completion block take a string as a parameter. Make your getLinkImage function call the completion block from inside the data task's completion block, wrapped in a dispatch_async that invokes the completion block on the main thread.

Edit:

Your modified getLinkImage method might look like this:

func getLinkImage(
  link_news: String, 
  separator: String,
  completion: (ok: Bool, resultString: String?) -> ()
  )
{
    let url = NSURL(string: link_news)
    var link_image_news = "http://www.website.com"
    let task = NSURLSession.sharedSession().dataTaskWithURL(url!) 
    {
     (data, response, error) -> Void in
        if error == nil {
            let urlContent = NSString(data: data!, 
              encoding: NSUTF8StringEncoding)
            //print(urlContent)
            let urlContentArray = 
              urlContent?.componentsSeparatedByString(separator)
            // search link's image
                print("----------Link's Image----------")
                var image_news = 
                  urlContentArray?[1].componentsSeparatedByString("<img alt=")
                image_news = image_news?[1].componentsSeparatedByString("src=")
                image_news = image_news?[1].componentsSeparatedByString("\"")
                link_image_news = "http://www.website.com" + image_news![1]
                print("the link of image is : "+link_image_news)
            // end of search link's image
            dispatch_async(dispatch_get_main_queue())
            {
              //We now have the string, so pass it to the completion block
              completion(true, link_image_news); 
            {
        }
        else {
            print("Error in the Image News load from Website")
            print(url!)
            dispatch_async(dispatch_get_main_queue())
            {
              //There was an error, so pass nil to completion
              completion(false, nil); 
            {
    }
    task.resume()
}

Upvotes: 1

Related Questions