7

いくつかのコンテキストを提供するには: 認証エラー (基本ではなくトークン認証を使用) 用のグローバル エラーハンドラーを実装しようとしています。グローバルにエラーが発生し、リクエストを繰り返します)

AFNetworkingOperationDidFinishNotification現在のアプローチは、再認証を行い、(認証が成功した場合) 元の要求を繰り返すためのオブザーバーを登録することです。

- (void)operationDidFinish:(NSNotification *)notification
{
    AFHTTPRequestOperation *operation = (AFHTTPRequestOperation *)[notification object];

    if(![operation isKindOfClass:[AFHTTPRequestOperation class]]) {
        return;
    }

    if(403 == [operation.response statusCode]) {
        // try to re-authenticate and repeat the original request
        [[UserManager sharedUserManager] authenticateWithCredentials...
            success:^{
                // repeat original request

                // AFHTTPRequestOperation *newOperation = [operation copy]; // copies too much stuff, eg. response (although the docs suggest otherwise)
                AFHTTPRequestOperation *newOperation = [[AFHTTPRequestOperation alloc] initWithRequest:operation.request];

                // PROBLEM 1: newOperation has no completion blocks. How to use the original success/failure blocks here?

                [self enqueueHTTPRequestOperation:newOperation];
            }
            failure:^(NSError *error) {
                // PROBLEM 2: How to invoke failure block of original operation?
            }
        ];
    }
}

ただし、リクエスト操作の完了ブロックに関するいくつかの問題に遭遇しました。

  • 元のリクエストを繰り返すとき、その完了ブロックを実行したいのは明らかです。ただし、AFHTTPRequestOperationは渡された成功ブロックと失敗ブロックへの参照を保持しません ( 「」を参照setCompletionBlockWithSuccess:failure:) 。NSOperationcompletionBlockAFURLConnectionOperation

    オペレーション コピーには含まれませんcompletionBlockcompletionBlock多くの場合、 への参照を強力にキャプチャします。これは、おそらく驚くべきことに、コピーされたときに元のself操作を指すことになります。

  • 再認証が失敗した場合に備えて、元のリクエストの失敗ブロックを呼び出したいと思います。繰り返しになりますが、これに直接アクセスする必要があります。

ここで何か不足していますか?代替アプローチのアイデアはありますか? 機能リクエストを提出する必要がありますか?

4

2 に答える 2

1

Art.syのポートフォリオアプリでこの問題を思いついた。私の最終的な結論は、失敗したときにさまざまなAFNetworking HTTP操作のコピーを作成する機能を持つNSOperationQueueサブクラスを作成することでした(そして、これをURLごとに最大3回実行してから、あきらめます)。

于 2012-10-27T13:55:23.407 に答える
0

次のことを試しましたか?

// set success / failure block of original operation
[newOperation setCompletionBlock:[operation.completionBlock copy]];
[operation setCompletionBlock:nil];

元の完了/失敗ブロックで self をキャプチャする (つまり、ivar にアクセスする) 場合、実際には newOperation の完了ブロックを実行するときに元の操作インスタンスにアクセスすることに注意してください。しかし、これはあなたが実際に望んでいることですよね?

通知ハンドラは、操作の完了ブロックの前に実行されます。したがって、元の操作の完了ブロックを nil に設定して、2 回実行されないようにする必要があります。

完了ブロックは、実行後に nil に設定されることに注意してください (AFURLConnectionOperation を参照)。

authenticateWithCredentials 失敗ブロックでは、何もしないでください。元の操作はその時点で終了しており、既にその障害ブロックを実行しています。

于 2012-10-28T10:42:20.733 に答える