ios 如何将 NSURLConnection 与 UIProgressView 集成?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/312796/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 15:24:30  来源:igfitidea点击:

How to integrate NSURLConnection with UIProgressView?

iosobjective-ciphonecocoa-touch

提问by jpm

I'm trying to integrate a NSURLConnection object with UIProgressView, so I can update the user while a file download is happening in the background.

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

I created a separate object to download the file in the background, and I'm having problems figuring out how to update the progress property in the UIProgressView object with the correct value. It's probably something very simple, but I cannot figure it out with Googling around.

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

Here's the code that I have:

这是我拥有的代码:

- (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]);
}

As you can see, the resourceDatamember variable holds the file data as it is being downloaded. The filesizemember variable holds the full size of the file, as returned by my web service in its Content-Length header.

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

It all works sort of OK, I keep getting the downloaded data with multiple executions of didReceiveDataas I should, but when I try to calculate the progress value, no proper value is returned. See below for a small sample of what I get in my console log:

一切正常,我一直按照我应该的方式通过多次执行didReceiveData来获取下载的数据,但是当我尝试计算进度值时,没有返回正确的值。有关我在控制台日志中获得的内容的小样本,请参见下文:

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

For reference, progressView.progressis a float. filesizeis a NSNumber that holds a long long. Finally, resourceLengthis a NSNumber that holds a NSUInteger.

作为参考,progressView.progress是一个浮点数。filesize是一个保存 long long 的 NSNumber。最后,resourceLength是一个保存 NSUInteger 的 NSNumber。

What am I missing here?

我在这里缺少什么?

回答by Dave Dribin

Not sure what I'm missing here, but your filesizebeing -1 seems to be your problem. The API docsclearly state that expectedContentLengthmay not be available and that NSURLResponseUnknownLengthis returned in these cases. NSURLResponseUnknownLengthis defined as:

不确定我在这里遗漏了什么,但你的filesize身分 -1 似乎是你的问题。该API文档明确指出,expectedContentLength可能无法使用,并且NSURLResponseUnknownLength在这种情况下返回。 NSURLResponseUnknownLength定义为:

#define NSURLResponseUnknownLength ((long long)-1)

In these cases, you cannot get an accurate progress. You'll need to handle this and display an indeterminate progress meter of some sort.

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

回答by Dave Dribin

I think you are printing out the file size wrong. If self.filesizeis indeed an NSNumber, you print it using the %@format, because it is an object, not a primitive:

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

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

By using the %d, your are just printing the pointervalue of self.filesize. To print out the actual long long value, use %lli(%dis only for 32-bit values):

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

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

So your self.filesize is actually-1 and the division is correct.

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

回答by Christian Fries

In your code, filesize appears to be an NSNumber object (!). So

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

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

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

and

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

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

will likely report something like the address (id) of that object (or something else). This is the

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

filesize: 4687472

filesize: 4687472

you see. As pointed out by others, the file size returned by the response is indeed -1, i.e.,

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

NSURLResponseUnknownLength

NSURLResponseUnknownLength

i.e., the server did not return the file size.

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