I have a function written in Swift 1.2, that checks for Reachability of Address or IP. Here it is :
func isHostConnected(hostAddress : String) -> Bool
{
var response : NSURLResponse?
let request = NSMutableURLRequest(URL: NSURL(string: hostAddress)!)
request.timeoutInterval = 3
let data = NSURLConnection.sendSynchronousRequest(request, returningResponse: &response, error: nil)
return ((response as? NSHTTPURLResponse)!.statusCode == 200)
}
Now since, NSURLConnection
is deprecated, as per Xcode suggestion I tried writing it using NSURLSession.dataTaskWithRequest
, here it is :
func isHostConnected(hostAddress : String) -> Bool
{
let request = NSMutableURLRequest(URL: NSURL(string: hostAddress.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!)!)
request.timeoutInterval = 3
let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration(), delegate: nil, delegateQueue: NSOperationQueue.mainQueue())
var responseCode = -1
session.dataTaskWithRequest(request, completionHandler: {(data : NSData?, response : NSURLResponse?, error : NSError?) -> Void in
responseCode = (response as? NSHTTPURLResponse)!.statusCode
})!.resume()
return (responseCode == 200)
}
Above code always returns false (its Obvious), since completionHandler
gets executed on seperate Thread.
My concern is that, can I make completionHandler()
run on MainThread somehow like sendSynchronousRequest
does by blocking it.
I have reasons to not to use 'Apple's Reachabilty' here.
Any suggestion will be helpful. :)
(Repeating my arguments from https://stackoverflow.com/a/30670518/1187415:)
Checking if a resource exists on a server requires sending a HTTP
request and receiving the response. TCP communication can take some
amount of time, e.g. if the server is busy, some router between the
client and the server does not work correctly, the network is down
etc.
That's why asynchronous requests are always preferred. Even if you
think that the request should take only milliseconds, it might
sometimes be seconds due to some network problems. And – as we all
know – blocking the main thread for some seconds is a big no-no.
That being said, you can use a "counting semaphore" or a "dispatch group" to wait for the completion of some asynchronous task.
You should not use this on the main thread. Blocking the main thread
for up to 3 seconds is not acceptable!
func isHostConnected(hostAddress : String) -> Bool
{
let request = NSMutableURLRequest(URL: NSURL(string: hostAddress.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!)!)
request.timeoutInterval = 3
request.HTTPMethod = "HEAD"
let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration())
var responseCode = -1
let group = dispatch_group_create()
dispatch_group_enter(group)
session.dataTaskWithRequest(request, completionHandler: {(_, response, _) in
if let httpResponse = response as? NSHTTPURLResponse {
responseCode = httpResponse.statusCode
}
dispatch_group_leave(group)
})!.resume()
dispatch_group_wait(group, DISPATCH_TIME_FOREVER)
return (responseCode == 200)
}
Remarks:
- Setting the HTTP method to "HEAD" is a small optimization, as the
server sends only the response header without the actual data.
- In the case of a illegal host name,
response
would be nil
, and
responseCode = (response as? NSHTTPURLResponse)!.statusCode
would crash.