I have a class to measure the bandwidth of the network using this answer. I tried to rewrite the class in Swift using the same functions:
class BandwidthChecker : NSObject, NSURLSessionDelegate, NSURLSessionDataDelegate {
var startTime = NSDate()
var endTime = NSDate()
var bytesReceived = 0
var completionHandler : ((speed: Double, error: ErrorType?)->Void)?;
override init() {
super.init()
}
func testDownloadSpeeWithURL(url: NSURL, timeout: NSTimeInterval, completionHandler: (speed: Double, error: ErrorType?)->Void) {
self.startTime = NSDate()
self.endTime = self.startTime
self.bytesReceived = 0
self.completionHandler = completionHandler
let configuration = NSURLSessionConfiguration.ephemeralSessionConfiguration()
configuration.timeoutIntervalForResource = timeout
configuration.timeoutIntervalForRequest = timeout
let session = NSURLSession(configuration: configuration, delegate: self, delegateQueue: nil)
session.dataTaskWithURL(url).resume()
}
func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveResponse response: NSURLResponse, completionHandler: (NSURLSessionResponseDisposition) -> Void) {
self.startTime = NSDate()
self.endTime = self.startTime
}
func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData) {
self.bytesReceived += data.length
self.endTime = NSDate()
}
func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {
let elapsed = self.endTime.timeIntervalSinceDate(self.startTime)
let speed = elapsed != 0 ? (Double(self.bytesReceived) / elapsed / 1024.0 / 1024.0 ) : -1
// timeout is no error, still measure speed
if error == nil || (error!.domain == NSURLErrorDomain && error!.code == NSURLErrorTimedOut) {
self.completionHandler!(speed: speed, error: nil)
} else {
self.completionHandler!(speed: speed, error: error)
}
}
}
I'm testing this code with a unit test (Yes its going to the "real" internet, I will mock it after I know its working):
func testBandwidth() {
let bandwithChecker = BandwidthChecker()
let asyncExpectation = expectationWithDescription("longRunningFunction")
var errorResult : ErrorType?
var speedResult : Double
speedResult = 0
bandwithChecker.testDownloadSpeeWithURL(NSURL(string: "http://download.thinkbroadband.com/1GB.zip")!, timeout: 10, completionHandler: {(speed, error) -> Void in
errorResult = error
speedResult = speed
asyncExpectation.fulfill()
})
self.waitForExpectationsWithTimeout(20) { error in
XCTAssertNil(error)
if errorResult != nil {
XCTFail("Error while measuring bandwith")
print("#error:",errorResult)
} else {
XCTAssert(speedResult>0)
print("##### SPEED #####\n")
print("speed: \(speedResult) MB/s\n")
print("#################\n")
}
}
}
This should give me a result after 10 secs, but apparently I get a timeout from waitForExpectationWithTimeout
after 20 secs. Breakpoints in didReceiveData
, didCompleteWithError
and didReceiveResponse
are not reached at all.
When I change the url in the test to an invalid url (e.g. "invalid url"
), the didCompleteWithError
does in fact trigger and gives me an invalid url error.
I'm helpless at this point. Is anybody out there who could hint me to the problem or give me a solution? Thanks guys, I really appreciate it!
Greetings j0h4nn3s