2016-06-16 18 views
0

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

+0

よく要求が明らかにタイムアウトしています。ネットワークをチェックし、デバイス上のエンドポイントにpingを実行して、他のプログラムを使用して到達可能かどうかを確認します。 – FruitAddict

+0

@FruitAddict NSURLSessionからエラーが発生しない場合、どのようにタイムアウトしますか?私はそれがうまくいくと思った:セッションの設定でタイムアウトを設定した場合、そのタイムアウトの後、didFinishWithErrorメソッドは以前に何が起こったのかということになりません。それはそうじゃないの? ファイルをブラウザの例からダウンロードできます。 – j0h4nn3s

答えて

0

かなりの研究の後、私は問題を見つけ、誰かが同じ問題を抱えている場合に回答を投稿します。

は、コード内でこの機能を見てみましょう:

func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveResponse response: NSURLResponse, completionHandler (NSURLSessionResponseDisposition) -> Void) { 
    self.startTime = NSDate() 
    self.endTime = self.startTime 
} 

対応Apple Docで見て解決策を提供します。 転送を続行するには、このような補完ハンドラを呼び出す必要があります。

completionHandler(NSURLSessionResponseDisposition.Allow) 
0

たぶん、あなたは代わりにブロックを使用してみてください?

let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { (data, response, error) -> Void in 
//log here to see if it gets called, and test for error 
} 

task?.resume() 
+0

デリゲートを使用して時間を正確に測定したい – j0h4nn3s

関連する問題