Swift 3:如何确定下载文件的网速?

Posted

技术标签:

【中文标题】Swift 3:如何确定下载文件的网速?【英文标题】:Swift 3: How to determine a downloaded file's internet speed? 【发布时间】:2016-12-17 06:03:54 【问题描述】:

我目前正在开发一个应用程序,该应用程序根据文件下载的速度确定用户的互联网连接速度。

我发现了一个类似的问题,@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:

有人可以提供帮助吗?谢谢

【问题讨论】:

【参考方案1】:

你应该用这个替换你的代码:

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)


【讨论】:

【参考方案2】:

错误 1

Error 是 Swift 3 中的协议。它是 Swift 2 中的 ErrorType。属性 domainNSError 的一部分。

我不能 100% 确定 URLSessionTask 是否总是在 didCompleteWithError 函数中传递 NSError,但我认为是这样。您可以尝试将error 转换为NSError 看看是否成功。

错误 2 和 3

错误信息似乎误导了我。但是当我查看speedTestCompletionHandler 的声明时,我注意到你不能使用参数标签。 _ 在函数参数前面意味着您必须省略参数标签。相反,您必须像这样调用speedTestCompletionHandler()

speedTestCompletionHandler(nil, error)
...
speedTestCompletionHandler(speed, nil)

【讨论】:

以上是关于Swift 3:如何确定下载文件的网速?的主要内容,如果未能解决你的问题,请参考以下文章

java运行环境JDE从官网下载网速很慢,有什么解决办法 或 如何安装JRE(Java 运行环境)

java用上传一个文件测试网速怎么写代码

如何确定何时从 Swift 中的集合中下载了所有图像?

网速/带宽与下载速度对照表

如何解决ajax在google chrome浏览器上失效

如何提高ftp的上传速度