【问题标题】:Where is the correct place to make HTTP requests in iOS?在 iOS 中发出 HTTP 请求的正确位置在哪里?
【发布时间】:2014-08-19 04:31:35
【问题描述】:

我有一个使用NSURLSessionDataTask 从服务器获取数据的应用程序。截至目前,我正在显示数据的UIViewControllerinit 方法中开始我的HTTP GET 请求。这是启动HTTP 请求的最佳/最智能的地方吗?如果没有,我应该在哪里做?

我问这个问题是因为当我退出我的应用程序并且它进入后台(并且没有被杀死)然后重新打开我的应用程序时,HTTP 请求不会被触发(因为它在UIViewControllers init 方法)并且显示的数据与服务器上的数据不是最新的。我试过把它放在viewDidLoad,但是进入前台时不会调用这个方法,viewWillAppear也不是viewDidAppear

我是否应该在appDelegate 中的UIApplications 生命周期方法之一中执行所有HTTP 请求?

简而言之,在iOS 中发出HTTP 请求的最佳位置在哪里?

谢谢,如果需要我可以发布代码或解释更多。

【问题讨论】:

  • 为什么不创建一个自定义对象来处理所有请求?最简单的是NSObject 的子类。
  • 如果您的应用程序包含多个viewControllers,您应该将HTTP请求发送到appDelegate并在didFinishLaunching方法中调用它并将所有数据存储到NSMutableDictionary并在所有viewControllers中使用它,您可以调用它didEnterForground 方法中的方法,因此每次将应用程序搁置时,所有数据都会刷新。您可以询问是否有任何采石场。
  • 好吧,我想把它放在didEnterForground 方法中。谢谢
  • viewWillAppear 应该在您退出并启动应用程序时被调用。只是好奇为什么它没有被调用。 :-/
  • @jithinroy viewWillAppear 根据我的经验是不可靠的。最好避免它,因为在很多情况下它不会被调用。

标签: ios objective-c uiviewcontroller httprequest nsurlsession


【解决方案1】:

首先,这是一个很大的问题,可能无法在这里完全回答,但希望我可以为您指明正确的方向,以便您学习如何钓鱼。 :)

要坚持模型-视图-控制器范式,您需要创建一个单独的对象来发出 HTTP 请求。 HTTP 请求将被视为模型的一部分。例如,这样做的好处是能够在您创建的其他 iOS 应用中使用您的模型。

至于将所有这些东西放在哪里以及最好的设计是什么......在您的问题中让我印象深刻的一件事是您希望应用程序中显示的数据与服务器上的数据保持同步.在高层次上,一个非常好的方法是使用 iOS 的多任务处理能力,并在您的应用程序处于后台时为您执行功能。您需要在操作系统中注册为在后台执行对服务器的提取的应用程序。

根据 Apple 的文档,“在 Xcode 5 及更高版本中,您可以从项目设置的 Capabilities 选项卡中声明应用支持的背景模式。启用 Background Modes 选项会将 UIBackgroundModes 键添加到应用的 Info.plist 文件中。”从那里您需要研究 UIApplicationDelegate 的协议方法 – application:performFetchWithCompletionHandler:-application:handleEventsForBackgroundURLSession:completionHandler:

此外,您还需要进一步研究 NSURLSession。如果要使用后台抓取,则不支持 NSURLSessionDataTask。您将需要使用 NSURLSessionDownloadTask,将响应保存到文件并根据需要进行处理。此外,正如上面的应用程序委托方法名称所暗示的那样,您需要阅读 NSURLSessionConfiguration 类参考,特别是关于 backgroundSessionConfiguration

所有这一切的真正酷之处在于,在您实现它之后,您的应用 UI 将为用户提供最新的 - 即使您的应用被用户或操作系统杀死。很漂亮。

祝你好运,希望这一切都会有所帮助。我希望我没有错过这里的任何其他重要作品。

【讨论】:

  • 谢谢,这很有帮助,我会更多地研究多任务处理。
【解决方案2】:

我认为这是个人喜好。所以我个人是在模型对象上做的。假设我有一个 Car 对象和一个 ShowroomViewController。我总是向 Car 对象声明一个类方法来调用服务来获取所有汽车。

@interaface Car

+(void)fetchCarsWithCompletionHandler:(void (^)(NSArray* cars, NSError *error ))handler;

-(void)getDetailsWithCompletionHandler:(void (^)(Car* car, NSError *error ))handler;
@end

然后调用viewWillAppear(如果我需要经常更新汽车)或viewDidload(如果我需要调用一次服务)上的类方法。

我主要做的另一个技巧是在视图控制器中定义一个标志,例如

@interface ShowroomViewController
@property(assign)BOOL needsModelUpdate;
@end

我有条件地更新模态。

@implementation ShowroomViewController
-(void)viewWillAppear:(BOOL)animated{
    if(self.needsModelUpdate){
       [self fetchModel]
    }
}



-(void)fetchModel{
     __block __weak ShowroomViewController *weakRef=self;
     [Car fetchCarsWithCompletionHandler:^(NSArray *cars, NSError *error) {
            [weakRef setCars:cars];
            [weakRef.tableView reloadData];
     }];
}
@end

我定义这个标志的原因是我可以在其他地方改变它,比如说 applicationDidEnterBackground: 方法来改变标志。或者你可以使用 KVO,但我总是觉得它有点矫枉过正。

【讨论】:

    【解决方案3】:

    随心所欲。

    就个人而言,我专门为与服务器的所有通信创建了一个类。实际上,我的应用程序有大约 20 个类,用于通信过程的不同部分。但你的可能没那么复杂。

    将类的实例作为对象添加到 xib 文件中,或者在应用委托的 init 方法中创建它的实例。

    使用 didEnterForeground 告诉其他类它需要做的事情,但仍然使用 init 方法来创建该类的实例。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-06
      • 1970-01-01
      • 2015-07-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多