this answerを使用してネットワークの帯域幅を測定するクラスがあります。 私は同じ機能を使用してスウィフトにクラスを書き換えてみました:NSURLSesssionDelegate NSURLSessionDataDelegate関数がdataTaskでトリガーしない
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)
}
}
}
私はユニットテストでこのコードをテストしています、私はその知った後(はいそのは「本当の」インターネットに行く、私はそれを模擬します)作業:
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")
}
}
}
これは私の10秒後の結果を与える必要がありますが、どうやら私は20秒後にwaitForExpectationWithTimeout
からタイムアウトを取得します。 didReceiveData
,didCompleteWithError
およびdidReceiveResponse
のブレークポイントにはまったく到達していません。
テストのURLを無効なURL(たとえば"invalid url"
)に変更すると、didCompleteWithError
が実際にトリガーされ、無効なURLエラーが表示されます。
私はこの時点で無力です。誰かが私に問題を示唆するか、解決策を教えてくれる人はいませんか?ありがとう、私は本当にそれを感謝します!
挨拶 j0h4nn3s
よく要求が明らかにタイムアウトしています。ネットワークをチェックし、デバイス上のエンドポイントにpingを実行して、他のプログラムを使用して到達可能かどうかを確認します。 – FruitAddict
@FruitAddict NSURLSessionからエラーが発生しない場合、どのようにタイムアウトしますか?私はそれがうまくいくと思った:セッションの設定でタイムアウトを設定した場合、そのタイムアウトの後、didFinishWithErrorメソッドは以前に何が起こったのかということになりません。それはそうじゃないの? ファイルをブラウザの例からダウンロードできます。 – j0h4nn3s