iOS AFNetworking downloadProgressBlock 计算返回负数

标签 ios progress-bar afnetworking afhttprequestoperation

我正在使用 AFNetworking 下载使用第三方类解析的数据。我以前曾多次使用 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];

最佳答案

我怀疑您会发现问题出在totalBytesExpectedToRead。具体来说,这来自 NSURLResponse 属性,expectedContentLengthas the docs say :

Return Value

The receiver’s expected content length, or NSURLResponseUnknownLength if the length can’t be determined.

Discussion

Some protocol implementations report the content length as part of the response, but not all protocols guarantee to deliver that amount of data. Clients should be prepared to deal with more or less data.

顺便说一下,这个常量 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,您可以选择使用不确定的进度 View (例如 UIActivityIndi​​catorView),这样可以完全避免这个问题。

最重要的是,进度的成功计算取决于您的服务器是否为预期字节提供合法值。如果您查看 totalBytesExpectedToRead,我敢打赌您得到的是 -1,结果是您好奇的计算进度百分比值。

关于iOS AFNetworking downloadProgressBlock 计算返回负数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18949678/

相关文章:

iOS 7 UISearchBar 定制当它是第一响应者

ios - 如何在 sprite kit 中创建进度条?

ios - UITapGestureRecognizer 在 Swift 的 SearchField 类中破坏了 UITableView didSelectRowAtIndexPath?

progress-bar - Vue 和 Axios 的进度条

android - 进度条显示背景

ios - 迁移到 swift 3 和 Xcode 8 时 cocoa pods 错误的解决方案是什么,问题详情在描述中?

ios - AF 网络 2.0 : credentials not sent to authentication within 30 seconds of previous request

ios - UITabBarController + UINavigationController 和更多选项卡黑屏问题

c# - 如何在加载某些控件时显示进度条?

ios - AFJSONRequestOperation 在 200 response.statusCode 上命中失败 block