function with dataTask returning a value [duplicate]
Asked Answered
S

5

10

I wan't to check if my url statusCode equals to 200, I created a function returning a Boolean if the statusCode equals to 200, I'm using a dataTask, but I don't know how to return a value:

class func checkUrl(urlString: String) -> Bool{

    let urlPath: String = urlString
    var url: NSURL = NSURL(string: urlPath)!
    var request: NSURLRequest = NSURLRequest(url: url as URL)
    var response: URLResponse?

    let session = Foundation.URLSession.shared


    var task = session.dataTask(with: request as URLRequest, completionHandler: {(data, response, error) in
        if let error = error {
            print(error)
        }

        if let data = data{
            print("data =\(data)")
        }
        if let response = response {
            print("url = \(response.url!)")
            print("response = \(response)")
            let httpResponse = response as! HTTPURLResponse
            print("response code = \(httpResponse.statusCode)")

            if httpResponse.statusCode == 200{
                return true
            } else {
                return false
            }
        }
    })
    task.resume()
}

The returns in if else are returning an error:

Unexpected non-void return value in void function

Senescent answered 13/10, 2016 at 7:29 Comment(0)
E
18

in order to return value you should use blocks. Try declaring your function like this:

class func checkUrl(urlString: String, finished: ((isSuccess: Bool)->Void) {

    let urlPath: String = urlString
    var url: NSURL = NSURL(string: urlPath)!
    var request: NSURLRequest = NSURLRequest(url: url as URL)
    var response: URLResponse?

    let session = Foundation.URLSession.shared


    var task = session.dataTask(with: request as URLRequest, completionHandler: {(data, response, error) in
        if let error = error {
            print(error)
        }

        if let data = data{
            print("data =\(data)")
        }
        if let response = response {
            print("url = \(response.url!)")
            print("response = \(response)")
            let httpResponse = response as! HTTPURLResponse
            print("response code = \(httpResponse.statusCode)")

            if httpResponse.statusCode == 200{
                finished(isSuccess: true)                
            } else {
                finished(isSuccess: false) 
            }
        }
    })
    task.resume()
}

And then call it like this:

checkUrl("http://myBestURL.com", finished { isSuccess in
// Handle logic after return here
})

Hope that this will help.

Entozoic answered 13/10, 2016 at 7:39 Comment(1)
This appears to no longer be applicable with the latest versions of Xcode.Metro
H
9

Consider semaphore if you want to keep your original return pattern.

func checkUrl(urlString: String) -> Bool {
    if let url = URL(string: fileUrl) {
        var result: Bool!

        let semaphore = DispatchSemaphore(value: 0)  //1. create a counting semaphore

        let session = URLSession.shared
        session.dataTask(with: url, completionHandler: { (data, response, error) in
            result = true  //or false in case
            semaphore.signal()  //3. count it up
        }).resume()

        semaphore.wait()  //2. wait for finished counting

        return result
    }

    return false
}
Hufuf answered 24/10, 2017 at 9:50 Comment(0)
E
1

Swift4, work in my case Try to add guard let data = data else { return } in dataTask like:

URLSession.shared.dataTask(with: request) { (data, response, error) in
    guard let data = data else { return }
    print("get some data")
}.resume()
Enravish answered 6/11, 2018 at 11:3 Comment(0)
H
0

You're returning a value from a Void function that is the completionHandler closure of dataTask(_:, _:)

Regarding your code, there is something wrong: you can't return that value because it's executed on a different thread, it's an asynchronous operation. Please take a look at this thread: Returning data from async call in Swift function

Huh answered 13/10, 2016 at 7:39 Comment(0)
G
0

I'm learning Swift too, here is how I got this to work.

In Swift, you can use a URLSessionDataTask to perform a network request and retrieve data asynchronously. To return data from a data task, you typically use a completion handler. Here's an example of how to do this:

import Foundation

func fetchDataFromURL(_ url: URL, completion: @escaping (Data?, Error?) -> Void) {
    let session = URLSession.shared
    let task = session.dataTask(with: url) { (data, response, error) in
        if let error = error {
            completion(nil, error)
            return
        }

        if let data = data {
            completion(data, nil)
        }
    }

    task.resume()
}

// Example usage
if let url = URL(string: "https://example.com/api/data") {
    fetchDataFromURL(url) { (data, error) in
        if let error = error {
            print("Error: \(error)")
        } else if let data = data {
            // Handle the retrieved data here
            print("Received data: \(data)")
        }
    }
}
Gelya answered 19/9, 2023 at 9:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.