iOS AFNetworking downloadProgressBlock 计算返回负数

Posted

技术标签:

【中文标题】iOS AFNetworking downloadProgressBlock 计算返回负数【英文标题】:iOS AFNetworking downloadProgressBlock calculation returning negative numbers 【发布时间】:2013-09-22 23:06:14 【问题描述】:

我正在使用 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];

【问题讨论】:

【参考方案1】:

我怀疑你会发现问题出在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% .后一种情况并不理想,但除非您的服务器报告准确的预期内容长度,否则您无能为力。

或者,如果您从未获得可靠的expectedContentLength,您可能会选择使用不确定的进度视图(例如UIActivityIndicatorView),这样可以完全避免这个问题。

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

【讨论】:

是的,就是这样。感谢您的详细回复。

以上是关于iOS AFNetworking downloadProgressBlock 计算返回负数的主要内容,如果未能解决你的问题,请参考以下文章

iOS进阶学习-初识AFNetworking

iOS网络开发之AFNetworking

iOS开发-AFNetworking

iOS开发之AFNetworking 3.0.4使用

iOS开发篇-AFNetworking网络封装(下载)

iOS ATS AFNetworking 单项认证