【问题标题】:How to integrate NSURLConnection with UIProgressView?如何将 NSURLConnection 与 UIProgressView 集成?
【发布时间】:2010-09-23 16:34:27
【问题描述】:

我正在尝试将 NSURLConnection 对象与 UIProgressView 集成,以便在后台下载文件时更新用户。

我创建了一个单独的对象来在后台下载文件,但在弄清楚如何使用正确的值更新 UIProgressView 对象中的进度属性时遇到了问题。这可能是非常简单的事情,但我无法通过谷歌搜索找到它。

这是我的代码:

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
    [self.resourceData setLength:0];
    self.filesize = [NSNumber numberWithLongLong:[response expectedContentLength]];
    NSLog(@"content-length: %d bytes", self.filesize);
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    [self.resourceData appendData:data];

    NSNumber *resourceLength = [NSNumber numberWithUnsignedInteger:[self.resourceData length]];
    NSLog(@"resourceData length: %d", [resourceLength intValue]);
    NSLog(@"filesize: %d", self.filesize);
    NSLog(@"float filesize: %f", [self.filesize floatValue]);
    progressView.progress = [resourceLength floatValue] / [self.filesize floatValue];
    NSLog(@"progress: %f", [resourceLength floatValue] / [self.filesize floatValue]);
}

如您所见,resourceData 成员变量保存正在下载的文件数据。 filesize 成员变量保存文件的完整大小,由我的 Web 服务在其 Content-Length 标头中返回。

一切正常,我通过多次执行 didReceiveData 继续获取下载的数据,但是当我尝试计算进度值时,没有返回正确的值。请参阅下面的控制台日志中的一小部分示例:

content-length: 4687472 bytes
resourceData length: 2904616
filesize: 4687472
float filesize: -1.000000
progress: -2904616.000000

作为参考,progressView.progress 是一个浮点数。 filesize 是一个持有 long long 的 NSNumber。最后,resourceLength 是一个包含 NSUInteger 的 NSNumber。

我在这里错过了什么?

【问题讨论】:

  • 运行此命令时控制台会记录什么?进度字段是否正确打印?
  • Ben,刚刚添加了控制台日志的示例。

标签: ios objective-c iphone cocoa-touch


【解决方案1】:

不确定我在这里缺少什么,但您的 filesize 为 -1 似乎是您的问题。 API docs 明确指出 expectedContentLength 可能不可用,并且在这些情况下返回 NSURLResponseUnknownLengthNSURLResponseUnknownLength 定义为:

#define NSURLResponseUnknownLength ((long long)-1)

在这些情况下,您无法获得准确的进度。您需要处理此问题并显示某种不确定的进度表。

【讨论】:

  • 戴夫,感谢您的回复。我在那里添加了一个额外的 NSLog() 调用来进一步说明我的观点。我在上面添加了一条记录“内容长度”的调试语句。
  • 我想我不明白这个问题,那么......你到底在问什么?
  • 我在问:我错过了什么?为什么 [self.filesize floatValue] 返回 -1 而不是其 NSNumber 对象的实际浮点值(表示 long long)?为什么里面的除法计算就这样彻底坏掉了?
  • 嗨,戴夫,我有一个问题,即内容长度未确定,即在我的情况下为 -1。那么您能否给我一个关于如何显示您正在谈论的“不确定进度表”的想法..提前谢谢! :)
  • @Zaraki:您应该使用 UIActivityIndi​​catorView 而不是 UIProgressView 来显示微调器。
【解决方案2】:

我认为您打印的文件大小错误。如果self.filesize 确实是NSNumber,则使用%@ 格式打印它,因为它是对象,而不是原始对象:

NSLog(@"filesize: %@", self.filesize);

通过使用%d,您只是在打印self.filesize 的指针 值。要打印出实际的 long long 值,请使用 %lli%d 仅适用于 32 位值):

NSLog(@"filesize: %lli", [self.filesize longLongValue]);

所以你的 self.filesize 实际上是 -1 并且划分是正确的。

【讨论】:

  • 戴夫,对于 NSLog() 错误来说,这很公平。但是,我真正想做的是计算一个浮点值(来自 2 个 NSNumber 对象)以分配给 progressView.progress。正如您在上面看到的,我在进行简单除法时没有得到预期值。
  • 你做得很好! 2904616 / -1 = -2904616
  • 更具体地说 2904616 / NSURLResponseUnknownLength = -2904616
  • 你真正的问题是文件大小确实持有-1并且你拒绝承认。 [self.filesize floatValue] 告诉你!如果您需要更有说服力,请尝试打印 [self.filesize longLongValue]。
  • 戴夫,你从一开始就是对的。我想为我的固执道歉,但我发送的是 Content-Length 标头,真正的问题是 mod_deflate 在发送我的文件数据之前将其删除。经过几次调整,现在一切正常。谢谢!
【解决方案3】:

在您的代码中,filesize 似乎是一个 NSNumber 对象 (!)。所以

NSLog(@"filesize: %d", self.filesize);

NSLog(@"content-length: %d bytes", self.filesize);

可能会报告该对象(或其他)的地址 (id)。这是

filesize: 4687472

你看。正如其他人指出的,响应返回的文件大小确实是-1,即

NSURLResponseUnknownLength

即服务器没有返回文件大小。

【讨论】:

    猜你喜欢
    • 2011-12-20
    • 1970-01-01
    • 1970-01-01
    • 2012-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-07
    • 2020-05-14
    相关资源
    最近更新 更多