【问题标题】:How do I access an AFHTTPRequest's Completion Block?如何访问 AFHTTPRequest 的完成块?
【发布时间】:2015-06-28 23:51:21
【问题描述】:

我在请求失败块中发布通知:

[manager    POST:path
    parameters:nil
    success:^(AFHTTPRequestOperation *operation, id responseObject) {
        if (operation.response.statusCode == 200) {
            //message delegate
        }
  } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
      [[NSNotificationCenter defaultCenter] postNotificationName:HOST_UNREACHABLE object:operation];
}];

在接收通知的方法中,completionBlock属性为nil。

如何在没有子类化和覆盖的情况下访问它?

【问题讨论】:

  • 你能澄清一下吗?您有一个需要完成和失败块的请求。在失败块中,您发布通知。其他一些对象观察通知并运行一个方法,该方法想要查看请求完成块?如果我有这个权利,请展示您如何初始化完成块,展示在通知时触发的另一个类中的方法。
  • @danh 完成,使用 AFNetworking 管理器
  • 抱歉,最后一部分还是没看懂。 nsnotification 的观察者永远不会获得块参数,它只会获得发布的通知。也许描述您希望在该方法中发生的事情并发布您迄今为止编码的内容。
  • 以操作为对象获取通知。当我从 notification.object.completionBlock 读取该对象时,它是 nil。
  • 抱歉 - 我错过了您将操作作为通知对象传递。我不能肯定地说,但是 AFHTTP 操作在调用错误时消除完成块是合理的,反之亦然。在它调用它之后将它运行的块清零也是一个好习惯。您可以将自己的一个或两个块的副本放在堆栈上(在一个范围为运行请求的方法的变量中)并将它们传递给通知。我可以向您展示如何做到这一点,但这似乎非常奇怪。你能解释一下你希望完成什么吗?

标签: objective-c afnetworking objective-c-blocks nsoperation afhttprequestoperation


【解决方案1】:

首先回答如何将块发送到 NSNotification 的问题:

您尝试执行此操作的方式很危险,因为我们不知道 AFHTTPSessionManager 如何处理您传递给它的块,并且除非它在公共接口中,否则它的作用可能不会随着时间的推移而保持不变。

因此,创建一个局部变量来表示您要传递的块,例如,completionBlock...

// this is a local variable declaration of the block
void (^completionBlock)(AFHTTPRequestOperation*,id) = ^(AFHTTPRequestOperation *operation, id response) {
    if (operation.response.statusCode == 200) {
        //message delegate
    }
};

[manager POST:path
    parameters:nil
    success:completionBlock
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    [[NSNotificationCenter defaultCenter] postNotificationName:HOST_UNREACHABLE object:completionBlock];
}];

观察者可以通过这种方式获取块并调用它...

- (void)didReceiveNotification:(NSNotification *)notification {
    void (^completionBlock)(AFHTTPRequestOperation*,id) = notification.object;

    // use it
    [manager POST:someOtherPath
        parameters:nil
        success:completionBlock
        // etc.
    ];
}

但我认为这种方法很奇怪。它分散了向收到通知的对象发出请求的责任,让它需要知道重试参数的路径(在这种情况下你没有,但有一天你可能会)。

考虑改为将管理器子类化并添加执行重试的行为。现在您的经理子类可以负责所有请求,包括重试,而您的其他类只是处理结果的客户。比如……

@interface MyAFHTTPRequestManager : AFHTTPSessionManager

- (nullable NSURLSessionDataTask *)POST:(NSString *)URLString
                      retryURL:(NSString *)retryURLString
                    parameters:(nullable id)parameters
                       success:(nullable void (^)(NSURLSessionDataTask *task, id responseObject))success
                       failure:(nullable void (^)(NSURLSessionDataTask *task, NSError *error))failure;

@end

让您的子类实现使用第一个 URLString 调用 super,并在失败时使用 retryURLString 调用 super。例如

- (nullable NSURLSessionDataTask *)POST:(NSString *)URLString
                      retryURL:(NSString *)retryURLString
                    parameters:(nullable id)parameters
                       success:(nullable void (^)(NSURLSessionDataTask *task, id responseObject))success
                       failure:(nullable void (^)(NSURLSessionDataTask *task, NSError *error))failure {

    [super POST:URLString parameters:parameters success:success
        failure:^(AFHTTPRequestOperation *operation, NSError *error) {
            [super POST:retryURLString parameters:parameters success:success failure:failure];
    }];
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-30
    • 2013-11-28
    • 1970-01-01
    • 2012-06-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多