web-dev-qa-db-ja.com

NSURLConnectionをUIProgressViewと統合する方法は?

NSURLConnectionオブジェクトをUIProgressViewと統合しようとしているので、ファイルのダウンロードがバックグラウンドで行われている間にユーザーを更新できます。

バックグラウンドでファイルをダウンロードするために別のオブジェクトを作成しましたが、UIProgressViewオブジェクトのprogressプロパティを正しい値で更新する方法を理解するのに問題があります。とてもシンプルなことかもしれませんが、グーグルで理解することはできません。

これが私が持っているコードです:

- (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 メンバー変数は、ダウンロード中のファイルデータを保持します。ザ・ ファイルサイズ メンバー変数は、WebサービスからContent-Lengthヘッダーに返される、ファイルのフルサイズを保持します。

それはすべてOKのように機能します、私はダウンロードされたデータを複数回実行して取得し続けます didReceiveData 必要に応じて、進捗値を計算しようとすると、適切な値が返されません。コンソールログに表示される内容の小さなサンプルについては、以下を参照してください。

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

参考のため、 progressView.progress フロートです。 ファイルサイズ longlongを保持するNSNumberです。最後に、 resourceLength NSUIntegerを保持するNSNumberです。

ここで何が欠けていますか?

24
jpm

ここで何が欠けているのかわかりませんが、filesizeが-1であることが問題のようです。 API docs は、expectedContentLengthが使用できない可能性があり、これらの場合はNSURLResponseUnknownLengthが返されることを明確に示しています。 NSURLResponseUnknownLengthは次のように定義されます。

#define NSURLResponseUnknownLength ((long long)-1)

このような場合、正確な進捗を得ることができません。これを処理し、ある種の不確定な進行状況メーターを表示する必要があります。

29
Dave Dribin

ファイルサイズを間違えて印刷していると思います。 self.filesizeが実際にNSNumberである場合、それはプリミティブではなくオブジェクトであるため、%@形式を使用して印刷します。

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

%dを使用すると、self.filesizeのpointer値を出力するだけです。実際のlonglong値を出力するには、%lliを使用します(%dは32ビット値のみです)。

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

したがって、self.filesizeは実際には -1であり、除算は正しいです。

6
Dave Dribin

コードでは、filesizeはNSNumberオブジェクト(!)のように見えます。そう

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

そして

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

そのオブジェクト(または他の何か)のアドレス(id)のようなものを報告する可能性があります。これは

filesize: 4687472

分かりますか。他の人が指摘しているように、応答によって返されるファイルサイズは確かに-1です。つまり、

NSURLResponseUnknownLength

つまり、サーバーはファイルサイズを返しませんでした。

0
Christian Fries