6

は初めてですMKNetworkKitが、プロジェクトに追加することができ、到達可能性の変更を処理する場合を除いて、完全に機能しています。

状況は次のとおりです。

  1. WiFiを無効にして、アプリを実行します。
  2. 到達可能性がなくても、サブクラスからPOSTを作成して、いくつかのデータを要求(使用)します。データを要求する直前に、操作はフリーズ可能として設定されます(Mugunth Kumarのドキュメントによる)。MKNetworkOperationMKNetworkEngine
  3. WiFiを有効にした後、checkAndRestoreFrozenOperationsinMKNetworkEngineが呼び出され、保留中の操作(到達可能性なしで作成された操作)が1つあることを検出し、エンキューを試みます。
  4. その後、私のonCompletionブロックは呼び出されません。

凍結操作+到達可能性について私が理解していないことはありMKNetworkKitますか?フリーズは、リクエストの開始後に到達可能性が変更される操作に対してのみ機能しますか?または、独自の到達可能性変更ブロックを実装する必要がありますか?

MKNetworkEngineこれは、操作を作成してリクエストを開始するサブクラスのコードです。無関係なコードが抑制されていることに注意してください。

NSMutableDictionary *params = [NSMutableDictionary dictionaryWithObject:@"value" forKey:@"param"];
MKNetworkOperation *op = [self operationWithPath:MYPATH
                                          params:params
                                      httpMethod:@"POST"];
[op setFreezable:YES];

[op onCompletion:^(MKNetworkOperation *completedOperation) {
   // ...
   // Here is where I process response and send the result to my completion block
   // It's called when WiFi is available, but not called otherwise.
   // ...
} onError:^(NSError *error) {
   // It's called when WiFi is available, but not called otherwise.
    DLog(@"Some error");
}];

[self enqueueOperation:op];

return op;
4

1 に答える 1

6

これらは2つの別々の問題です:再開と完了。

  1. 再開:フリーズ/フリーズ解除メカニズムは、キャッシュが有効になっている場合にのみ機能します

    AppDelegateで-useCacheを呼び出す必要があります-didFinishLaunchingWithOptions:

    self.networkEngine = [[MKNetworkEngine alloc] init ...];
    [self.networkEngine useCache]; // <- Add this line
    
  2. complete:ネットワークステータスの変更時(つまり、フリーズ解除後)に完了コールバックが呼び出されない

    ただし、アクション(1.)を実行し、MKNetworkOperation.m -checkAndRestoreFrozenOperationsの次の行にブレークポイントを設定すると、次のようになります。

    [self enqueueOperation:pendingOperation]
    

    ネットワーク接続が復元されたときに呼び出され、pendingOperation 保留中のPOSTであることがわかります。ただし、新しいMKNetworkOperationがインスタンス化されているため(その時点で完了ブロックが存在しなくなっている可能性があります)、onCompletionブロックが呼び出されることはありません。考えられる回避策の1つは、コールバックの代わりに通知を使用することです。

  3. 完全な修正:起動全体で機能する(2)よりも堅牢なアプローチは、^{}ブロックコールバックをNSNotificationsに置き換えることです。AppDelegateのように、リスナーを早期に登録します。MKNetworkKit通知に精通するために必要な最小限の変更は次のとおりです。

    3a。MKNetworkOperation.hに通知定数を挿入します

    #define MKNetworkOperationCompletionNotification @"MKNetworkOperationCompletionNotification"
    #define MKNetworkOperationErrorNotification @"MKNetworkOperationErrorNotification"
    

    3b。MKNetworkOperation.m -operationSucceededで成功通知をブロードキャストします(この通知をメインスレッドからリッスンしてUIを変更できるようにpostNotificationOnMainThreadを使用していることに注意してください。メインスレッドのNSOperationとNSNotificationCenterを参照してください):

    -(void) operationSucceeded {
        NSDictionary * aUserInfo = [NSDictionary dictionaryWithObjectsAndKeys:
            self, NSStringFromClass([MKNetworkOperation class]),
            nil];
        NSNotification * notification = [NSNotification notificationWithName:MKNetworkOperationCompletionNotification
            object:nil
            userInfo:aUserInfo];
        [[NSNotificationCenter defaultCenter] postNotificationOnMainThread:notification];
        ...
    

    3c。MKNetworkOperation.mで失敗通知をブロードキャストします-operationFailedWithError

    -(void) operationFailedWithError:(NSError*) error {
        self.error = error;
        NSDictionary * aUserInfo = [NSDictionary dictionaryWithObjectsAndKeys:
            self,   NSStringFromClass([MKNetworkOperation class]),
            error,  NSStringFromClass([NSError class]),
            nil];
        NSNotification * notification = [NSNotification notificationWithName:MKNetworkOperationErrorNotification
            object:nil
            userInfo:aUserInfo];
    
        [[NSNotificationCenter defaultCenter] postNotificationOnMainThread:notification];
        ...
    

    3d。AppDelegateのようなかなり永続的なオブジェクトをリスナーとして登録します(登録を解除することを忘れないでください)。

        // Listen to POST changes
        NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
        [defaultCenter addObserver:self
            selector:@selector(mkNetworkOperationCompletionNotification:)
            name:MKNetworkOperationCompletionNotification
            object:nil];
        [defaultCenter addObserver:self
            selector:@selector(mkNetworkOperationErrorNotification:)
            name:MKNetworkOperationErrorNotification
            object:nil];
    

    3e。リスナーがどのように見えるかのサンプルコード:

    - (void)mkNetworkOperationCompletionNotification:(NSNotification*)notification {
        MKNetworkOperation *operation = [[notification userInfo]
            objectForKey:NSStringFromClass([MKNetworkOperation class])];
        NSLog(@"operationSucceeded: %@", [operation responseString]);
    }
    
    - (void)mkNetworkOperationErrorNotification:(NSNotification*)notification {
        NSError * error = [[notification userInfo] objectForKey:NSStringFromClass([NSError class])];
        NSLog(@"operationFailedWithError: %@", [error localizedDescription]);
    }
    

これを行うと、完了です。バツ。

前の回答でMKNetworkOperation.hに提案された不要な変更を削除するように編集し、^ {}の制限を克服する方法を示すために段落3を追加しました。

于 2013-04-25T04:42:58.677 に答える