0

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

redoff
  • 1,124
  • 11
  • 18
  • You can't wait for a async method to finish to return your link_image_news otherwise your method wouldn't be async. You will need to implement a completion handler. – Leo Dabus Feb 12 '16 at 16:10
  • how can i do completion handler in my situation ? – redoff Feb 12 '16 at 16:18
  • check this link and you will see many answers using completion handlers http://stackoverflow.com/questions/24231680/loading-image-from-url/27712427#27712427 – Leo Dabus Feb 12 '16 at 16:20
  • the problem is the function return the initialization value not the right value. how can i solve this ? i look for many completion handler examples but i dont really understand how can i implement it ! – redoff Feb 12 '16 at 16:22
  • just pass the string as the result at your completion handler – Leo Dabus Feb 12 '16 at 16:23
  • 1
    thank you @LeoDabus, your link helped me – redoff Feb 13 '16 at 12:30

1 Answers1

1

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()
}
Community
  • 1
  • 1
Duncan C
  • 128,072
  • 22
  • 173
  • 272
  • looks nice, i copied your code but in the function call (in viewDidLoad() ) what arguments should i give to completion ? ("ok" and "resultString") – redoff Feb 12 '16 at 17:05
  • Your question doesn't really make sense. What do you mean "what arguments should you give to completion? What data from the download to you need to make available to the code that gets run once the download is complete? Take a look at my answer on this thread for a working example: http://stackoverflow.com/questions/30235082/storing-values-in-completionhandlers-swift – Duncan C Sep 06 '16 at 23:16