1

I've taken over some Swift 2 code and trying to bring it up to Swift 3 (Xcode 8.3), but I'm stuck on one line.

The code is checking to see if a host is connected:

func isHostConnected(hostAddress : String) -> Bool {
    let request = NSMutableURLRequest(url: NSURL(string: hostAddress.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)!)! as URL)
    request.timeoutInterval = 3
    request.httpMethod = "HEAD"

    let session = URLSession(configuration: URLSessionConfiguration.default)
    var responseCode = -1

    let group = DispatchGroup.init()
    group.enter()

    session.dataTask(with: request as URLRequest, completionHandler: {(_, response, _) in
        if let httpResponse = response as? HTTPURLResponse {
            responseCode = httpResponse.statusCode
        }
        group.leave()
    }).resume()

    group.wait(timeout: dispatch_time_t(DispatchTime.distantFuture)) //ERROR LINE
    return (responseCode == 401)
}

I am getting an error on the line:

group.wait(timeout: dispatch_time_t(DispatchTime.distantFuture))

which reads:

Cannot invoke initializer for type 'dispatch_time_t' with an argument list of type '(DispatchTime)'

So it seems to be looking for an object of type DispatchTime as the parameter but I can't seem to find an answer on Google to match .distantFuture

Also, if I try:

group.wait(timeout: dispatch_time_t(.distantFuture))

I get an error saying:

Type of expression is ambiguous without more context

Thanks.

eoinzy
  • 2,152
  • 4
  • 36
  • 67

2 Answers2

1

It's way simpler actually :)

group.wait(timeout: .distantFuture)

Or if you'd like to wait say 5 seconds:

group.wait(timeout: .now() + .seconds(5))

Beautiful right

See also this way better answer

Apart from that...you should consider what @vadian says in his comment :)

Hope that helps.

Community
  • 1
  • 1
pbodsk
  • 6,787
  • 3
  • 21
  • 51
1

First of all, to answer your question, it's simply

group.wait(timeout: .distantFuture)

Second of all, it's very bad programming habit to wait in this case. There is no reason at all. The most efficient way to be notified asynchronously is to use a completion handler.

It's much less code, the code uses the Swift 3 native structs URL and URLRequest and considers also the case of a bad URL to prevent a crash:

func isHostConnected(hostAddress : String, completion: @escaping (Bool)->()) {
    guard let escapedString = hostAddress.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed),
          let url = URL(string: escapedString) else {
             completion(false)
             return
    }
    var request = URLRequest(url: url)
    request.timeoutInterval = 3
    request.httpMethod = "HEAD"

    let session = URLSession(configuration: URLSessionConfiguration.default)
    session.dataTask(with: request, completionHandler: {(_, response, _) in
        if let httpResponse = response as? HTTPURLResponse {
            completion(httpResponse.statusCode == 401)
        }
        completion(false)
    }).resume()
}

And use it:

isHostConnected(hostAddress: "http://meyserver.com") { isConnected
    print("Host is connected:", isConnected)
}
vadian
  • 274,689
  • 30
  • 353
  • 361