Objective-C:如何从 POST 方法返回响应?

Posted

技术标签:

【中文标题】Objective-C:如何从 POST 方法返回响应?【英文标题】:Objective-C: How to return response from POST method? 【发布时间】:2014-11-16 04:43:20 【问题描述】:

我有一个POST 方法,看起来像

+ (id) post 
    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
    manager.requestSerializer = [AFJSONRequestSerializer serializer];
    [manager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
    manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"application/json"];
    id response = nil;
    [manager POST:@"https://mapp.com/oauth/register"
       parameters:@@"email" : @"e", @"memberExternalId" : @"m"
          success:^(AFHTTPRequestOperation *operation, id responseObject) 
              response =  responseObject;
           failure:^(AFHTTPRequestOperation *operation, NSError *error) 
                // (todo) alert on failure
                NSLog(@"Error: %@", error);
            ];
    return response;

我想抽象出这个方法以便我可以重用它,所以我创建了id response

但是当我分配时

response =  responseObject;

我得到编译错误

Variable is declared outside the block and is not assignable  

问题

我怎样才能保留response 以便我以后可以返回它。

【问题讨论】:

修改块内的变量时必须使用__block说明符 @gabbler 是的,如果这是一个同步方法,那将是正确的。但事实并非如此,所以从这个函数返回值的整个想法是行不通的。他应该使用完成处理程序模式(很像POST 方法本身)。 【参考方案1】:

您正在调用使用完成块模式的异步方法,因此您应该这样做。所以

将返回类型改为void

将块参数添加到您的方法中;

POST 完成块中,如果提供了completionHandler,请调用它;

因此:

+ (void) postWithCompletionHandler:(void (^)(id responseObject, NSError *error))completionHandler 
    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
    manager.requestSerializer = [AFJSONRequestSerializer serializer];

    // these lines not needed
    //
    // [manager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
    // manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"application/json"];

    [manager POST:@"https://mapp.com/oauth/register"
       parameters:@@"email" : @"e", @"memberExternalId" : @"m"
          success:^(AFHTTPRequestOperation *operation, id responseObject) 
              if (completionHandler) 
                  completionHandler(responseObject, nil);
              
           failure:^(AFHTTPRequestOperation *operation, NSError *error) 
              if (completionHandler) 
                  completionHandler(nil, error);
              
          ];

因此,您可以这样称呼它:

[MyClass postWithCompletionHandler:^(id responseObject, NSError *error) 
    if (!responseObject) 
        NSLog(@"failed: %@", error);
        return;
    

    // use the `responseObject` here
];

// Note, because the above is asynchronous, don't try to use `responseObject` here.
// You can only use it inside the above `completionHandler` block.

顺便说一句,您可能不想为每个请求都实例化一个新的AFHTTPRequestOperationManager。所以我个人 (a) 将 AFHTTPRequestOperationManager 设为此类的属性; (b) 将操作管理器的实例化移动到类的一些初始化方法中; (c) 使这个“执行请求”方法成为实例方法,而不是类方法。它在这里不是那么重要,但是当您考虑将来发出许多请求的功能时,在所有地方实例化新的请求操作管理器是低效的。

【讨论】:

如果call B 依赖于call A 等,如何建模synchronistic 行为?是completionHandler?是首选方式吗?我很困惑,因为代码变得非常嵌套且难以理解 是的,这是首选方式。如果您发现由于所有这些嵌套而使您的代码变得笨拙,那么请进行功能分解,将嵌套代码移动到您将从完成块调用的自己的方法中。虽然您可以考虑其他技术来使这个固有的异步过程以同步方式运行(例如信号量)或在不同任务/操作之间建立依赖关系(例如调度组通知或操作队列依赖关系),恕我直言,不建议使用这些方法。跨度>

以上是关于Objective-C:如何从 POST 方法返回响应?的主要内容,如果未能解决你的问题,请参考以下文章

如何从Objective-C中的异步内部函数内部返回外部函数

如何从Objective-C中的异步内部函数内部返回外部函数

从 Objective-C 中的 ColdFusion 布尔返回类型获取 BOOL 的更好方法?

从 Objective-C 到 Swift 的 Swift 传递块

如何使用objective-c格式化从youtube api v3 reuqest返回的持续时间?

让 Objective-C 方法返回任何东西