当可达性改变时,MKNetworkKit操作不会恢复/完成

时间:2012-10-30 13:24:41

标签: ios network-programming mknetworkkit mknetworkengine

我是MKNetworkKit的新手,但我已经能够将它添加到我的项目中,除非处理可达性更改,否则它完全正常工作。

情况如下:

  1. 我禁用WiFi并运行该应用程序。
  2. 即使没有可访问性,我也会通过从POST子类创建MKNetworkOperation来请求(使用MKNetworkEngine)一些数据。在请求数据之前,操作被设置为freezable(根据Mugunth Kumar's doc)。
  3. 启用WiFi后,checkAndRestoreFrozenOperations中的MKNetworkEngine被调用,它会检测到有一个待处理操作(创建一个没有可达性的操作),它会尝试入队。
  4. 之后,我的onCompletion块永远不会被调用。
  5. 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;
    

1 个答案:

答案 0 :(得分:6)

这是两个不同的问题:简历与完成。

  1. resume:冻结/解冻机制仅在启用缓存时有效

    您必须在AppDelegate -didFinishLaunchingWithOptions中调用-useCache:

    self.networkEngine = [[MKNetworkEngine alloc] init ...];
    [self.networkEngine useCache]; // <- Add this line
    
  2. 完成:在网络状态发生变化时(即解冻后),调用完成回调

    然而,如果您采取行动(1.)并在MKNetworkOperation.m -checkAndRestoreFrozenOperations 中放置一个断点:

    [self enqueueOperation:pendingOperation]
    

    您会发现在恢复网络连接时会调用它,而 pendingOperation 是您的待处理POST。但是,由于已经实例化了新的MKNetworkOperation(到那时完成块可能不再存在),因此永远不会调用onCompletion块。一种可能的解决方法是使用通知而不是回调。

  3. 完整修复:比启动更有效的方法(2)可以替换NSNotifications的^{}块回调。尽早注册您的听众,就像在AppDelegate中一样。以下是使MKNetworkKit通知变得精通所需的最小更改:

    3a。在MKNetworkOperation.h中插入通知常量

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

    3b。在MKNetworkOperation.m -operationSucceeded中广播成功通知(请注意,我使用postNotificationOnMainThread,以便可以从主线程收听所述通知并更改UI;请参阅{{3} }):

    -(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]);
    }
    
  4. 这样做,你已经完成了。 X

    编辑在上一个答案中删除对MKNetworkOperation.h的不必要的建议更改,并添加第3段以说明如何克服^ {}限制。