使用AFNetwork进行GET请求并保存响应 [英] GET request using AFNetworking and saving response

查看:90
本文介绍了使用AFNetwork进行GET请求并保存响应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用AFNetworking做一个简单的GET请求

I am doing a simple GET request with AFNetworking

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:@"http://someapi.com/hello.json" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
    NSLog(@"JSON: %@", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    NSLog(@"Error: %@", error);
}];

发出请求后,我希望能够访问 responseObject 来自该类中的任何其他方法。

Once I have made the request I want to be able to access the responseObject from any other method in the class.

我希望能够保存responseObject,以便可以执行类似在tableview。

I want to be able to save the responseObject so I can do something like display the output in a tableview.

推荐答案

创建由JSON表示的对象模型是很常见的。得到响应后,您便可以将数据解析到模型中。我们使用的方法是通过完成块将响应返回给请求者。您不必将JSON解析为强类型的对象,但是从长远来看,这确实很有用。最好将网络请求操作也分配到一个单独的类(称为服务)中。这样,您可以实例化新服务,并通过完成块通知它已完成。例如,您的服务的请求签名可能看起来像这样:

It's common to creat object models that will be represented by JSON. When you get the response you would then parse the data into the models. The approach we use is to return the response to the requester through a completion block. You don't have to parse the JSON into strongly typed objects, but it really is helpful long term. It's probably a good idea to farm out the network request operations into a separate class (called a service) as well. This way you can instantiate a new service and get notified through a completion block that it is finished. For example your service's request signature could look like this:

typedef void(^HelloWorldCompletionHandler)(NSString *helloWorld, NSError *error);


- (void)requestHelloWorldData:(HelloWorldCompletionHandler)completionHandler;

// implementation
- (void)requestHelloWorldData:(HelloWorldCompletionHandler)completionHandler {
   AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
   [manager GET:@"http://someapi.com/hello.json" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {

    id JSONResponse = [operation responseObject];
    if (operation.error) {
        completionHandler(nil, error);
    } else {
        // parse the response to something
        id parserResult = [self parseJSONResponse:JSONResponse];
        completionHandler(parserResult, nil);
    }
 }];

这样,您将知道网络请求何时完成,并且可以设置所需的数据在您班级的某个物业上。然后,您可以调用tableView.reloadData以使用表中的数据。

This way you'll know when the network request is complete, and you can set the data you want on a property within your class. Then you could call tableView.reloadData in order to use the data in your table.

所有这些代码都将放入服务类型类中。我喜欢按职责组织服务。我不知道您要调用多少个不同的数据,但我们的项目有几个。例如,如果您要制作天气应用,则可以按当前状况,每日天气预报和每小时天气预报进行组织。我将为每个请求提供服务。假设我创建了CurrentConditionsService。标题看起来像这样:

All that code would go into a service type class. I like to organize my services by responsibility. I don't know how many different data calls you make, but we have several for our project. If for instance you were making a weather app you could potentially organize by Current Conditions, Daily Forecasts, and Hourly Forecasts. I would make a service for each one of these requests. Say I created a CurrentConditionsService. The header would look something like this:

typedef void(^CurrentConditionsCompletionHandler)(CurrentConditions *currentConditions, NSError *error);

@interface CurrentConditionsService : NSObject

// locationKey is some unique identifier for a city
+ (instancetype)serviceWithLocationKey:(NSString *)locationKey;

- (void)retrieveCurrentConditionsWithCompletionHandler:(CurrentConditionsCompletionHandler)completionHandler;

@end

然后在我的实现文件中提出请求并像我上面演示的那样调用给定的完成处理程序。许多不同的服务都可以遵循此模式,以便所有服务都可以从处理请求/响应部分的基类继承。然后,您的子类可以重写特定的方法,并根据类型适当地处理/解析数据。

Then in my implementation file I would make the request and invoke the given completion handler like I demonstrated above. This pattern can be followed by many different services to the point where all your services could inherit from a base class that handles the request/response portions. Then your subclasses could override specific methods and handle/parse the data appropriately based on type.

如果您采用将JSON响应解析为模型对象的路线,则所有解析器将需要符合协议。通过这种方式,在您的超类中,解析器的具体实现是什么都没有关系。您为超类提供了一个具体的实现,它所知道的所有操作就是调用解析器并返回响应。

If you go the route of parsing the JSON responses into model objects, all your parsers will need to conform to a protocol. This way in your super class it doesn't matter what the concrete implementation of your parser is. You supply the super class with a concrete implementation and all it knows how to do is invoke the parser and return the response.

示例JSON解析器协议如下所示:

An example JSON parser protocol would look like this:

@protocol AWDataParser <NSObject>

@required
- (id)parseFromDictionary:(NSDictionary *)dictionary;
- (NSArray *)parseFromArray:(NSArray *)array;

@end

并在您的服务超类中调用它:

And invoking it in your services super class:

- (id)parseJSONResponse:(id)JSONResponse error:(NSError **)error {

    NSAssert(self.expectedJSONResponseClass != nil, @"parseResponse: expectedJSONResponseClass cannot be nil");
    NSAssert(self.parser != nil, @"parseResponse: parser cannot be nil");

    id parserResult = nil;
    if (![JSONResponse isKindOfClass:self.expectedJSONResponseClass]) {
        //handle invalid JSON reponse object
        if (error) {
            *error = [NSError errorWithDomain:NetworkServiceErrorDomain code:kNetworkServiceErrorParsingFailure userInfo:@{@"Invalid JSON type": [NSString stringWithFormat:@"expected: %@, is: %@",self.expectedJSONResponseClass,  [JSONResponse class]]}];
        }
    } else {
        if (self.expectedJSONResponseClass == [NSArray class]) {
            parserResult = [self.parser parseFromArray:JSONResponse];
        }else {
            parserResult = [self.parser parseFromDictionary:JSONResponse];
        }
        if (!parserResult) {
            if (error) {
                *error = [NSError errorWithDomain:NetworkServiceErrorDomain code:kNetworkServiceErrorParsingFailure userInfo:nil];
            }
        }
    }

    return parserResult;
}

这篇关于使用AFNetwork进行GET请求并保存响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆