Synchronous URL request on Swift 2

If you really wanna do it synchronously you can always use a semaphore:

func send(url: String, f: (String) -> Void) {
    var request = NSURLRequest(URL: NSURL(string: url)!)
    var error: NSErrorPointer = nil
    var data: NSData

    var semaphore = dispatch_semaphore_create(0)

    try! NSURLSession.sharedSession().dataTaskWithRequest(request) { (responseData, _, _) -> Void in
        data = responseData! //treat optionals properly
        dispatch_semaphore_signal(semaphore)
    }.resume()

    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)

    var reply = NSString(data: data, encoding: NSUTF8StringEncoding)
    f(reply)
}

EDIT: Add some hackish ! so the code works, don’t do this in production code

Swift 3.0+ (3.0, 3.1, 3.2, 4.0)

func send(url: String, f: (String) -> Void) {
    guard let url = URL(string: url) else {
        print("Error! Invalid URL!") //Do something else
        return
    }

    let request = URLRequest(url: url)
    let semaphore = DispatchSemaphore(value: 0)

    var data: Data? = nil

    URLSession.shared.dataTask(with: request) { (responseData, _, _) -> Void in
        data = responseData
        semaphore.signal()
    }.resume()

    semaphore.wait(timeout: .distantFuture)

    let reply = data.flatMap { String(data: $0, encoding: .utf8) } ?? ""
    f(reply)
}

Leave a Comment