我有一个使用NSURLSessionDataTask
从服务器获取数据的应用。截至目前,我正在显示数据的HTTP
GET
方法中启动init
UIViewController
个请求。这是启动HTTP
请求的最佳/最聪明的地方吗?如果没有,我应该在哪里做?
我问这个问题,因为当我退出我的应用并进入后台(并且没有被杀)然后重新打开我的应用程序时,HTTP
请求没有被解雇(因为它位于UIViewControllers
init
方法中,并且显示的数据与服务器上的内容不是最新的。我已尝试将其放入viewDidLoad
,但在进入前台时不会调用此方法,viewWillAppear
和viewDidAppear
也不会调用此方法。
我应该在HTTP
的{{1}}生命周期方法之一中执行所有UIApplications
次请求吗?
简而言之,appDelegate
中提出HTTP
请求的最佳位置在哪里?
谢谢,如果需要,我可以发布代码或解释更多。
答案 0 :(得分:2)
首先,这是一个很大的问题,可能无法在这里完全回答,但希望我可以指出你正确的方向,这样你就可以学习如何捕鱼。 :)
要坚持使用模型 - 视图 - 控制器范例,您需要创建一个单独的对象来发出HTTP请求。 HTTP请求将被视为模型的一部分。这样做的好处是能够在您创建的其他iOS应用程序中使用您的模型。
至于在哪里放置所有这些东西以及什么是最好的设计....在你的问题中让我感到震惊的一件事是你希望你的应用程序中显示的数据是最新的在服务器上。从高层次来说,一个非常好的方法是使用iOS的多任务处理功能,并在应用程序处于后台时为您执行功能。您需要在操作系统中注册为在后台执行提取到服务器的应用程序。
根据Apple的文档,"在Xcode 5及更高版本中,您可以从项目设置的“功能”选项卡声明应用支持的背景模式。启用“背景模式”选项会将UIBackgroundModes键添加到应用程序的Info.plist文件中。"从那里你需要研究UIApplicationDelegate的协议方法 - application:performFetchWithCompletionHandler:和 -application:handleEventsForBackgroundURLSession:completionHandler:。
此外,您还需要更多地了解NSURLSession。如果要使用后台提取,则不支持NSURLSessionDataTask。您将需要使用NSURLSessionDownloadTask,将响应保存到文件并根据需要进行处理。此外,正如上面的app委托方法名称所暗示的那样,您需要阅读NSURLSessionConfiguration类参考,特别是 backgroundSessionConfiguration 。
关于所有这一切的真正酷的是,在您实施之后,您的应用UI将为用户提供最新信息 - 即使您的应用被用户或操作系统杀死。非常漂亮。
祝你好运,希望这一切都有所帮助。我希望我在这里不会错过任何其他大片。答案 1 :(得分:1)
我认为这是个人喜好。所以我个人在模型对象上做。假设我有一个Car对象和一个ShowroomViewController。我总是向Car对象声明一个类方法来调用服务来获取所有的汽车。
@interaface Car
+(void)fetchCarsWithCompletionHandler:(void (^)(NSArray* cars, NSError *error ))handler;
-(void)getDetailsWithCompletionHandler:(void (^)(Car* car, NSError *error ))handler;
@end
然后在viewWillAppear上调用class方法(如果我需要经常更新汽车)或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,但我总觉得它太过分了。
答案 2 :(得分:0)
随心所欲。
就个人而言,我专门为与服务器的所有通信创建了一个类。实际上,我的应用程序有大约20个类用于通信过程的不同部分。但你的可能不那么复杂了。
在xib文件中添加类的实例作为对象,或者在app delegate的init方法中创建它的实例。
使用didEnterForeground告诉其他类它需要做它的东西,但仍然使用init方法来创建类的实例。