2013-09-22 34 views
3

我正在使用AFNetworking下載與第三方類分析的數據。我之前使用過AFNetworking多次執行類似的操作,但由於某種原因,當我調用downloadProgressBlock並使用我的進度條進行計算時,數字會返回負值。請看下圖:iOS AFNetworking downloadProgressBlock計算返回負數

2013-09-22 16:04:06.036 Portland Police[2228:60b] Download = -31849.000000 
2013-09-22 16:04:06.041 Portland Police[2228:60b] Download = -40537.000000 
2013-09-22 16:04:06.042 Portland Police[2228:60b] Download = -44881.000000 
2013-09-22 16:04:06.044 Portland Police[2228:60b] Download = -53569.000000 
2013-09-22 16:04:06.046 Portland Police[2228:60b] Download = -62257.000000 
2013-09-22 16:04:06.048 Portland Police[2228:60b] Download = -63705.000000 
2013-09-22 16:04:06.085 Portland Police[2228:60b] Download = -70945.000000 
2013-09-22 16:04:06.087 Portland Police[2228:60b] Download = -89769.000000 
2013-09-22 16:04:06.089 Portland Police[2228:60b] Download = -94113.000000 
2013-09-22 16:04:06.100 Portland Police[2228:60b] Download = -98457.000000 
2013-09-22 16:04:06.104 Portland Police[2228:60b] Download = -102801.000000 
2013-09-22 16:04:06.111 Portland Police[2228:60b] Download = 1.000000 

下面是我的代碼:

// Get the URL we are going to use to parse with 
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:@"http://www.portlandonline.com/scripts/911incidents.cfm"]]; 
NSURLRequest *request = [httpClient requestWithMethod:@"GET" path:nil parameters:nil]; 
AFHTTPRequestOperation *operation = [httpClient HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) { 

    NSLog(@"Response = %@", operation); 

    // Empty our calls out 
    [self.originalArray removeAllObjects]; 

    // Initiate our parser 
    MWFeedParser *parser = [[MWFeedParser alloc] init]; 
    parser.delegate = self; 
    [parser startParsingData:responseObject textEncodingName:[operation.response textEncodingName] withCompletionHandler:^(NSError *error, MWFeedParser *parser) { 

     // If theres no error 
     if (!error) { 

      // Return the success block 
      success(operation.request, operation.request.URL, self.calls); 
     } 
     else { 

      // Return the failure block 
      failure(operation.request, operation.request.URL, error); 
     } 
    }]; 

} failure:^(AFHTTPRequestOperation *operation, NSError *error) { 

    NSLog(@"AFHTTPRequestOperation Failure: %@", error); 

    // Return our failure block 
    failure(operation.request, operation.request.URL, error); 
}]; 
[operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) { 

    NSLog(@"Download = %f", (float)totalBytesRead/totalBytesExpectedToRead); 

}]; 
[operation start]; 

回答

7

我懷疑你會發現這個問題是totalBytesExpectedToRead。具體地,該來自NSURLResponse屬性,expectedContentLength,其as the docs say

返回值

接收機的預期內容長度,或如果NSURLResponseUnknownLength無法確定的長度。

討論

一些協議實現報告內容長度作爲響應的一部分,但不是所有的協議保證將數據傳送的量。客戶應該準備好處理更多或更少的數據。

順便說一句,這個常數,NSURLResponseUnknownLength,等於-1,這將解釋您的計算值。這只是系統通知您無法確定響應時間的方式。

因此,在最壞的情況下,您會得到-1作爲預期的字節數。即使它不是-1,它也不是完全可靠的(尤其是如果你寫了你自己的服務器代碼的問題)。您的應用必須優雅地處理向您的應用報告的任何expectedContentLength。大多數情況下,如果你得到一個非負值,你通常會得到一個可以有效用於「完成百分比」計算的值,但不要依賴它(例如,你可能會收到更多的字節或比expectedContentLength報告更少的字節)。優雅地處理特殊的價值。

例如,設置我的進度條的時候,我已經做了一些類似:

CGFloat progress; 

if (expectedContentLength > 0 && progressContentLength <= expectedContentLength) 
    progress = (CGFloat) progressContentLength/expectedContentLength; 
else 
    progress = (progressContentLength % 1000000l)/1000000.0f; 

這給了我,慢慢進展到100%的收益下載進度條,如果我有好的預期內容長度值,但是否則會顯示一個進度條,對於下載的每1,000,000個字節,進度條從0%到100%。後一種情況並不理想,但除非您的服務器報告準確的預期內容長度,否則您可以做的不多。

或者,如果您從未得到可靠的expectedContentLength,則可以選擇使用不確定進度視圖(例如UIActivityIndicatorView),這樣可以完全避免此問題。

底線,成功計算進度取決於您的服務器是否爲預期的字節提供合法值。如果你看看totalBytesExpectedToRead,我敢打賭你會得到-1,並且看到你的好奇的計算進度百分比值。

+0

沒錯,就是這樣。感謝您的詳細回覆。 –