extension URLSession {
/*
* synchronousDataTask
*
* Httpデータを同期的に取得します。スレッドをブロックするので使用に注意してください。
*/
func synchronousDataTask(with request:URLRequest) -> (data:Data?, response:URLResponse?, error:Error?) {
let semaphore = DispatchSemaphore(value: 0)
var _dat : Data?
var _res : URLResponse?
var _err : Error?
self.dataTask(with: request) { dat, res, err in
_dat = dat; _res = res; _err = err
semaphore.signal()
}.resume()
_ = semaphore.wait(timeout: .distantFuture)
return (_dat, _res, _err)
}
func synchronousDataTask(with url:URL) -> (data:Data?, response:URLResponse?, error:Error?) {
return self.synchronousDataTask(with: URLRequest(url: url))
}
/*
* retryDataTask
*
* Httpデータ取得に失敗た場合に再度取得を試みます。取得に成功するまでtimesで指定した回数の再取得を試みます。
*/
func retryDataTask(withRequest request:URLRequest, times num:Int=50, wait usec:useconds_t=200*1000, errorHandler:@escaping (Int, Error) -> ()={_,_ in}, completionHandler:@escaping (Data?, URLResponse?, Error?) -> ()) -> URLSessionDataTask {
return self.dataTask(with: request) { dat, res, err in
if let err = err, num > 0 {
errorHandler(num, err)
usleep(usec)
self.retryDataTask(withRequest: request, times: num-1, wait: usec, errorHandler: errorHandler, completionHandler: completionHandler).resume()
} else {
completionHandler(dat, res, err)
}
}
}
func retryDataTask(withURL url:URL, times num:Int=50, wait usec:useconds_t=200*1000, errorHandler:@escaping (Int, Error) -> ()={_,_ in}, completionHandler:@escaping (Data?, URLResponse?, Error?) -> ()) -> URLSessionDataTask {
return self.retryDataTask(withRequest: URLRequest(url: url), times: num, wait: usec, errorHandler: errorHandler, completionHandler: completionHandler)
}
}