2

ファイルのダウンロードを含むデータ処理を監視するための NSProgress オブジェクトのツリーがあります。ダウンロードは、バックグラウンド構成で NSURLSession を使用して行われます。

プロセスを開始すると、最上位の NSProgress オブジェクトが予期しない fractionCompleted の数値を報告します。問題をデバッグして (そして「Hello World」アプリケーションに分離して)、[NSURLSession downloadTaskWithRequest:] を呼び出した結果として NSProgress オブジェクトが作成され、上記のメソッドを呼び出した直後にその fractionCompleted プロパティが 1.0 であることがわかりました。この NSProgress オブジェクトは私の NSProgress ツリーの一部を取得するため、進行状況をオフセットすると、ツリーの上位に表示されます。

このサンプル アプリケーションでは、ダウンロードと並行してダミーのバックグラウンド タスクも開始しています。このタスクは、NSProgress オブジェクトを通じて進行状況を報告します。私がそうした理由は、NSURLSession が NSProgress オブジェクトを作成しない場合 (Apple が主張していること)、NSProgress ツリーに少なくとも 1 つのダウンが存在するためです。

ダウンロードとダミー タスクを起動した直後に NSProgress ツリーをログに記録すると、NSProgress ツリーは次のようになります。

<NSProgress: 0x7ff8dae06b10> : Parent: 0x0 / Fraction completed: 0.5000 / Completed: 0 of 1  
  <_NSProgressGroup: 0x7ff8dae0f450> : Portion of parent: 1 Children: 1
    <NSProgress: 0x7ff8dae0f880> : Parent: 0x7ff8dae06b10 / Fraction completed: 0.5000 / Completed: 0 of 100  
      <_NSProgressGroup: 0x7ff8dae0fec0> : Portion of parent: 100 Children: 2
        <NSProgress: 0x7ff8dad74b90> : Parent: 0x7ff8dae0f880 / Fraction completed: 1.0000 / Completed: 1 of 1  
        <NSProgress: 0x7ff8daf036c0> : Parent: 0x7ff8dae0f880 / Fraction completed: 0.0000 / Completed: 0 of 100

その結果、進捗レポートが奇妙になります。

ダウンロードを開始する呼び出し ([self resumeDownload]) をコメントアウトすると、NSProgress ツリーは次のようになります。

<NSProgress: 0x7febca52ac90> : Parent: 0x0 / Fraction completed: 0.0000 / Completed: 0 of 1  
  <_NSProgressGroup: 0x7febca529e60> : Portion of parent: 1 Children: 1
    <NSProgress: 0x7febca529ff0> : Parent: 0x7febca52ac90 / Fraction completed: 0.0000 / Completed: 0 of 100  
      <_NSProgressGroup: 0x7febca52ced0> : Portion of parent: 100 Children: 1
        <NSProgress: 0x7febca52d780> : Parent: 0x7febca529ff0 / Fraction completed: 0.0000 / Completed: 0 of 100

ご覧のとおり、fractionCompleted = 1.0 の余分な NSProgress オブジェクトはなく、進捗レポートは問題ありません。

NSURLSessionまたはその下にあるものでない場合、fractionCompleted = 1.0のNSProgressがどこから来ているのかわかりません。(Apple は、NSURLSession は NSProgress オブジェクトを作成しないと述べています。) この動作は、iOS 8 でのみ iOS 7 で確認できます (GM リリースであっても)。

バックグラウンド設定で NSURLSession を使用していることに注意してください! デフォルト構成では、問題は存在しません。

「予期しない」NSProgress オブジェクトが fractionCompleted = 1.0 で表示されるのはなぜですか? NSProgress API の使い方が間違っていますか? iOS 7 と 8 で動作が大きく異なる原因は何ですか?

サンプルコードはこちらから入手できます: https://s3-eu-west-1.amazonaws.com/pg.test/pubtest/NSProgress-20140830.zip

事前に助けてくれてありがとう。

4

1 に答える 1

3

アップロードの進行状況で同じ問題が発生しました。あなたが言ったように、タスクを作成するための呼び出しは、現在の進行状況にバインドされ、すぐに完了する NSProgress オブジェクトを作成しているようです。

uploadTask = [self.session uploadTaskWithRequest:request fromFile:fileURL];

これにより、全体的な進捗に問題が発生しました。AFNetworking フォークで、ブロックを介して NSProgress を作成するコールバックを持つ回避策を作成しました。AFURLSessionManager のメソッドが更新され、進行状況出力パラメーターではなく進行状況作成ブロックが追加されました。

- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request
                                     fromFile:(NSURL *)fileURL
                                 progress:(NSProgress *(^)(int64_t totalUnitCount))progressCreationBlock
                            completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler

これにより、「progress」ブロックで作成された進行状況オブジェクトのみが、現在の進行状況の直接の子として追加され、セッションの作成からの進行状況は追加されないことが保証されます。呼び出し先からのブロックの実装は次のようになります。

progress:^NSProgress *(int64_t totalUnitCount) {
    [currentProgress becomeCurrentWithPendingUnitCount:1];

    NSProgress *progress = [NSProgress progressWithTotalUnitCount:totalUnitCount];

    [currentProgress resignCurrent];

    return progress;
} 

https://github.com/cgreen-mmf/AFNetworking/commit/a0703a4f82a47e6c56c11245e4d88846ffbd0b28

これが iOS 8 のバグなのか、それとも意図した動作なのかはわかりません。

于 2014-10-03T16:15:11.840 に答える