Swift3:如何判断下载文件的网速?
Swift 3: How to determine a downloaded file's internet speed?
我目前正在开发一款应用,该应用可根据文件下载速度确定用户的互联网连接速度。
我发现了一个类似的问题,@Rob 在 Swift 中提供了答案:Right way of determining internet speed in iOS 8
目前我正在使用 Swift 3,并尝试将他的代码从旧的 Swift 转换如下:
var startTime: CFAbsoluteTime!
var stopTime: CFAbsoluteTime!
var bytesReceived: Int!
var speedTestCompletionHandler: ((_ megabytesPerSecond: Double?, _ error: NSError?) -> ())!
func testDownloadSpeedWithTimout(timeout: TimeInterval, completionHandler:@escaping (_ megabytesPerSecond: Double?, _ error: NSError?) -> ())
{
let url = URL(string: "http://www.someurl.com/file")!
startTime = CFAbsoluteTimeGetCurrent()
stopTime = startTime
bytesReceived = 0
speedTestCompletionHandler = completionHandler
let configuration = URLSessionConfiguration.default
configuration.timeoutIntervalForResource = timeout
let session = URLSession(configuration: configuration, delegate: self, delegateQueue: nil)
session.dataTask(with: url).resume()
}
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data)
{
bytesReceived! += data.count
stopTime = CFAbsoluteTimeGetCurrent()
}
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?)
{
let elapsed = stopTime - startTime
guard elapsed != 0 && (error == nil || (error?.domain == NSURLErrorDomain && error?.code == NSURLErrorTimedOut)) else {
speedTestCompletionHandler(megabytesPerSecond: nil, error: error)
return
}
let speed = elapsed != 0 ? Double(bytesReceived) / elapsed / 1024.0 / 1024.0 : -1
speedTestCompletionHandler(megabytesPerSecond: speed, error: nil)
}
我设法转换了大部分代码,但我似乎遇到了一些错误2:
有人可以提供帮助吗?谢谢
你应该用这个替换你的代码:
class ViewController: UIViewController, URLSessionDelegate, URLSessionDataDelegate
{
override func viewDidLoad()
{
super.viewDidLoad()
testDownloadSpeedWithTimout(timeout: 5.0) { (megabytesPerSecond, error) -> () in
print("\(megabytesPerSecond); \(error)")
}
}
var startTime: CFAbsoluteTime!
var stopTime: CFAbsoluteTime!
var bytesReceived: Int!
var speedTestCompletionHandler: ((_ megabytesPerSecond: Double?, _ error: NSError?) -> ())!
/// Test speed of download
///
/// Test the speed of a connection by downloading some predetermined resource. Alternatively, you could add the
/// URL of what to use for testing the connection as a parameter to this method.
///
/// - parameter timeout: The maximum amount of time for the request.
/// - parameter completionHandler: The block to be called when the request finishes (or times out).
/// The error parameter to this closure indicates whether there was an error downloading
/// the resource (other than timeout).
///
/// - note: Note, the timeout parameter doesn't have to be enough to download the entire
/// resource, but rather just sufficiently long enough to measure the speed of the download.
func testDownloadSpeedWithTimout(timeout: TimeInterval, completionHandler:@escaping (_ megabytesPerSecond: Double?, _ error: NSError?) -> ()) {
let url = NSURL(string: "http://www.someurl.com/file")!
startTime = CFAbsoluteTimeGetCurrent()
stopTime = startTime
bytesReceived = 0
speedTestCompletionHandler = completionHandler
let configuration = URLSessionConfiguration.ephemeral
configuration.timeoutIntervalForResource = timeout
let session = URLSession(configuration: configuration, delegate: self, delegateQueue: nil)
session.dataTask(with: url as URL).resume()
}
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data)
{
bytesReceived! += data.count
stopTime = CFAbsoluteTimeGetCurrent()
}
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?)
{
let elapsed = stopTime - startTime
guard elapsed != 0 && (error == nil || ((error! as NSError).domain == NSURLErrorDomain && error?._code == NSURLErrorTimedOut)) else{
speedTestCompletionHandler(nil, error as? NSError)
return
}
let speed = elapsed != 0 ? Double(bytesReceived) / elapsed / 1024.0 / 1024.0 : -1
speedTestCompletionHandler(speed, error as? NSError)
}
}
错误 1
Error
是 Swift 中的协议 3. 它是 Swift 中的 ErrorType
2. 属性 domain
是 属性 domain
的一部分NSError
.
我不是 100% 确定 URLSessionTask
是否总是在 didCompleteWithError
函数中传递 NSError
,但我认为是的。您可以尝试将 error
转换为 NSError
并查看是否成功。
错误 2 和 3
错误信息似乎误导了我。但是当我查看 speedTestCompletionHandler
的声明时,我注意到,您不能使用参数标签。 _
在函数参数前面的意思是,你必须省略参数标签。相反,您必须这样调用 speedTestCompletionHandler()
:
speedTestCompletionHandler(nil, error)
...
speedTestCompletionHandler(speed, nil)
我目前正在开发一款应用,该应用可根据文件下载速度确定用户的互联网连接速度。
我发现了一个类似的问题,@Rob 在 Swift 中提供了答案:Right way of determining internet speed in iOS 8
目前我正在使用 Swift 3,并尝试将他的代码从旧的 Swift 转换如下:
var startTime: CFAbsoluteTime!
var stopTime: CFAbsoluteTime!
var bytesReceived: Int!
var speedTestCompletionHandler: ((_ megabytesPerSecond: Double?, _ error: NSError?) -> ())!
func testDownloadSpeedWithTimout(timeout: TimeInterval, completionHandler:@escaping (_ megabytesPerSecond: Double?, _ error: NSError?) -> ())
{
let url = URL(string: "http://www.someurl.com/file")!
startTime = CFAbsoluteTimeGetCurrent()
stopTime = startTime
bytesReceived = 0
speedTestCompletionHandler = completionHandler
let configuration = URLSessionConfiguration.default
configuration.timeoutIntervalForResource = timeout
let session = URLSession(configuration: configuration, delegate: self, delegateQueue: nil)
session.dataTask(with: url).resume()
}
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data)
{
bytesReceived! += data.count
stopTime = CFAbsoluteTimeGetCurrent()
}
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?)
{
let elapsed = stopTime - startTime
guard elapsed != 0 && (error == nil || (error?.domain == NSURLErrorDomain && error?.code == NSURLErrorTimedOut)) else {
speedTestCompletionHandler(megabytesPerSecond: nil, error: error)
return
}
let speed = elapsed != 0 ? Double(bytesReceived) / elapsed / 1024.0 / 1024.0 : -1
speedTestCompletionHandler(megabytesPerSecond: speed, error: nil)
}
我设法转换了大部分代码,但我似乎遇到了一些错误2:
有人可以提供帮助吗?谢谢
你应该用这个替换你的代码:
class ViewController: UIViewController, URLSessionDelegate, URLSessionDataDelegate
{
override func viewDidLoad()
{
super.viewDidLoad()
testDownloadSpeedWithTimout(timeout: 5.0) { (megabytesPerSecond, error) -> () in
print("\(megabytesPerSecond); \(error)")
}
}
var startTime: CFAbsoluteTime!
var stopTime: CFAbsoluteTime!
var bytesReceived: Int!
var speedTestCompletionHandler: ((_ megabytesPerSecond: Double?, _ error: NSError?) -> ())!
/// Test speed of download
///
/// Test the speed of a connection by downloading some predetermined resource. Alternatively, you could add the
/// URL of what to use for testing the connection as a parameter to this method.
///
/// - parameter timeout: The maximum amount of time for the request.
/// - parameter completionHandler: The block to be called when the request finishes (or times out).
/// The error parameter to this closure indicates whether there was an error downloading
/// the resource (other than timeout).
///
/// - note: Note, the timeout parameter doesn't have to be enough to download the entire
/// resource, but rather just sufficiently long enough to measure the speed of the download.
func testDownloadSpeedWithTimout(timeout: TimeInterval, completionHandler:@escaping (_ megabytesPerSecond: Double?, _ error: NSError?) -> ()) {
let url = NSURL(string: "http://www.someurl.com/file")!
startTime = CFAbsoluteTimeGetCurrent()
stopTime = startTime
bytesReceived = 0
speedTestCompletionHandler = completionHandler
let configuration = URLSessionConfiguration.ephemeral
configuration.timeoutIntervalForResource = timeout
let session = URLSession(configuration: configuration, delegate: self, delegateQueue: nil)
session.dataTask(with: url as URL).resume()
}
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data)
{
bytesReceived! += data.count
stopTime = CFAbsoluteTimeGetCurrent()
}
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?)
{
let elapsed = stopTime - startTime
guard elapsed != 0 && (error == nil || ((error! as NSError).domain == NSURLErrorDomain && error?._code == NSURLErrorTimedOut)) else{
speedTestCompletionHandler(nil, error as? NSError)
return
}
let speed = elapsed != 0 ? Double(bytesReceived) / elapsed / 1024.0 / 1024.0 : -1
speedTestCompletionHandler(speed, error as? NSError)
}
}
错误 1
Error
是 Swift 中的协议 3. 它是 Swift 中的 ErrorType
2. 属性 domain
是 属性 domain
的一部分NSError
.
我不是 100% 确定 URLSessionTask
是否总是在 didCompleteWithError
函数中传递 NSError
,但我认为是的。您可以尝试将 error
转换为 NSError
并查看是否成功。
错误 2 和 3
错误信息似乎误导了我。但是当我查看 speedTestCompletionHandler
的声明时,我注意到,您不能使用参数标签。 _
在函数参数前面的意思是,你必须省略参数标签。相反,您必须这样调用 speedTestCompletionHandler()
:
speedTestCompletionHandler(nil, error)
...
speedTestCompletionHandler(speed, nil)