4

AFNetworking で作成された iOS アプリケーションがあります。シングルトンのカスタム httpclient サブクラスがあり、それを使用して API を使用し、サーバーからバイナリ ファイルをダウンロードします。

約100個のファイルをダウンロードする必要があります。URL 配列を繰り返し処理し、URL ごとに 1 つの AFHTTPRequestionOperation を作成しても安全ですか? 私のコードはこれです:

NSMutableURLRequest* rq = [[MIHTTPClient sharedInstance] requestWithMethod:@"GET" path:@"...." parameters:nil];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:rq] ;
operation.outputStream = [NSOutputStream outputStreamToFileAtPath:path append:NO];

[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
    //completion

} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    //manage error
}];


[[MIHTTPClient sharedInstance] enqueueHTTPRequestOperation:operation];

このキューからフィードバックを受け取るにはどうすればよいですか? 「HTTPClientDelegate」プロトコルなどは表示されません。

4

1 に答える 1

5

進捗状況については、setDownloadProgressBlock(の一部、サブクラス化AFURLConnectionOperationされている)を参照してください。例:AFHTTPRequestOperation

[operation setDownloadProgressBlock:^(NSInteger bytesWritten, NSInteger totalBytesWritten, NSInteger totalBytesExpectedToWrite) {
    NSLog(@"Sent %d of %d bytes, %@", totalBytesWritten, totalBytesExpectedToWrite, path);
}];

また、コードサンプルでは、​​を呼び出しsetCompletionBlockWithSuccess:failure:ているので、個々の操作の完了に関するステータスが提供されます。個人的には、私の小さなテストでは、要求されたダウンロードの配列を維持し、次の3つのブロック(進行状況、成功、失敗)でダウンロードのステータスコードを次のように更新します。

for (NSInteger i = 0; i < 20; i++)
{
    NSURLRequest *request = ... // set the request accordingly

    // create a download object to keep track of the status of my download

    DownloadObject *object = [[DownloadObject alloc] init];
    download.title = [NSString stringWithFormat:@"Download %d", i];
    download.status = kDownloadObjectStatusNotStarted;
    [self.downloadObjects addObject:download];

    AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];

    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
        download.status = kDownloadObjectStatusDoneSucceeded;

        // update my UI, for example, I have table view with one row per download
        //
        // [self.tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:i inSection:0]]
        //                       withRowAnimation:UITableViewRowAnimationNone];
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        download.status = kDownloadObjectStatusDoneFailed;

        // update UI
        //
        // [self.tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:i inSection:0]]
        //                       withRowAnimation:UITableViewRowAnimationNone];
    }];

    [operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {
        download.totalBytesRead = totalBytesRead;
        download.status = kDownloadObjectStatusInProgress;

        // update UI
        //
        // [self.tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:i inSection:0]]
        //                       withRowAnimation:UITableViewRowAnimationNone];
    }];

    [queue addOperation:operation];
}

この方法で、個々のダウンロードを追跡できます。保留中の操作を追跡することもできます(またはHTTPClientオブジェクトのoperationQueueプロパティを照会して、そのoperationCountプロパティを確認することもできます)。


100個のファイルをダウンロードする場合、2つの考慮事項があります。

  • AFNetworkingコードを見ると、サブクラスsetMaxConcurrentOperationCountのを適切な数(4または5)に設定して呼び出したいと思いますが、そうではないようです。それをはるかに超えると収穫逓減が見られ、すべてのファイルが単一のサーバーからのものである場合、特定のクライアントと特定のサーバー間で実行できる同時操作の数に制約があります。operationQueueHTTPClient

  • 私は、Appleがセルラーネットワークを介して異常な要求を行うアプリを拒否するという逸話的な主張を読みました。https://stackoverflow.com/a/14922807/1271826を参照してください。

于 2013-03-01T17:16:39.783 に答える