提出许多网络请求的iOS应用程序的最佳架构?

时间:2011-01-26 21:33:40

标签: iphone objective-c cocoa-touch network-programming asihttprequest

我正在重新思考我正在开发的大型应用程序的请求架构的方法。我目前正在使用ASIHTTPRequest实际发出请求,但由于在不同的视图控制器中采取了许多不同的操作,我需要许多不同类型的请求,我正在尝试找出组织这些请求的最佳系统。

我目前正在构建由应用代表保留的单身“请求者”,并坐在那里听取需要发出请求信号的NSNotifications;他们发出请求,听取响应,并发送带有响应数据的新NSNotification。这解决了我的大多数问题,但没有优雅地处理失败的请求或同时请求同一个单一请求者。

任何人都有成功设计一个清晰的OO架构,可以在iOS应用程序中制作许多不同类型的请求吗?

4 个答案:

答案 0 :(得分:69)

在尝试了几种方法之后,这是一个给我优秀结果,易于记录,理解,维护和扩展的架构:

  • 我有一个对象负责网络连接,我们称之为“网络管理员”。通常,此对象是单例(使用Matt Gallagher's Cocoa singleton macro创建)。
  • 由于您使用ASIHTTPRequest(我总是这样做,很棒的API),我在网络管理器中添加了一个ASINetworkQueue ivar。我让网络管理员成为该队列的代表。
  • 我为我的应用需要的每种网络请求创建ASIHTTPRequest的子类(通常,对于每个后端REST交互或SOAP端点)。这有另一个好处(详见下文:):
  • 每当我的一个控制器需要一些数据(refresh,viewDidAppear等)时,网络管理器就会创建所需ASIHTTPRequest子类的实例,然后将其添加到队列中。
  • ASINetworkQueue会处理带宽问题(取决于您使用的是3G,EDGE还是GPRS或Wifi,您拥有更多带宽,还可以处理更多请求等)。这是由队列完成的,这很酷(至少,这是我理解这个队列的事情之一,我希望我没有弄错:)。
  • 每当请求完成或失败时,都会调用网络管理器(请记住,网络管理器是队列的委托)。
  • 网络管理员不知道如何处理每个请求的结果;因此,它只是在请求上调用方法!请记住,请求是ASIHTTPRequest的子类,因此您可以只放置管理请求结果的代码(通常,将JSON或XML反序列化为实际对象,触发其他网络连接,更新Core Data存储等)。将代码放入每个单独的请求子类中,使用具有跨请求类的通用名称的多态方法,使调试和管理IMHO变得非常容易。
  • 最后,我使用通知向上述控制器通知有趣事件;使用委托协议不是一个好主意,因为在您的应用程序中,您通常有许多控制器与您的网络管理器通信,然后通知更灵活(您可以让多个控制器响应相同的通知等)。

无论如何,这就是我一直在做的事情,坦率地说它运作得很好。我可以水平扩展系统,根据需要添加更多ASIHTTPRequest子类,并且网络管理器的核心保持不变。

希望它有所帮助!

答案 1 :(得分:1)

以下是我一般的做法。我也有一个用于发出网络请求的单例对象。对于必须经常发出的请求,我有一个接受AFHTTPRequestOperations(或AFJSONRequestOperations)的NSOperationQueue,因为我通常使用AFNetworking来发出请求。对于这些,有一个completionBlock和failureBlock属性,在请求成功或失败时执行。在我的单例对象上,我将有一个启动特定网络请求的方法,并且作为该方法的参数,我将包括一个成功和失败块,可以将其传递到方法中定义的块。这样,整个应用程序可以发出网络请求,此时应用程序的范围可用于传递给该方法的块中的单例。例如......(使用ARC)

        @implementation NetworkManager

    -(void)makeRequestWithSuccess:(void(^)(void))successBlock failure:(void(^)(NSError *error))failureBlock

    {
        NSURL *url = [NSURL URLWithString:@"some URL"];

        NSURLRequest *request = [NSURLRequest requestWithURL:url];

        AFHTTPRequestOperation *op = [[AFHTTPRequestOperation alloc] initWithRequest:request];

        [op setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
            [responseObject doSomething];

            if (successBlock)
                dispatch_async(dispatch_get_main_queue(), successBlock);

        } failure:^(AFHTTPRequestOperation *operation, NSError *error) {

            if (failureBlock)
                dispatch_async(dispatch_get_main_queue(), ^{
                    failureBlock(error);
                });
        }];

        [self.operationQueue addOperation:op];
    }
@end

你总是可以让成功块接受你需要传递的任何参数。

答案 2 :(得分:0)

fully-loaded项目读得很好。

答案 3 :(得分:0)

试用STNetTaskQueue,这可以使您的请求可重复使用且可维护。