如何在 iOS 中使用 AFNetworking 从 REST 接口定期轮询/拉取
Posted
技术标签:
【中文标题】如何在 iOS 中使用 AFNetworking 从 REST 接口定期轮询/拉取【英文标题】:How to periodically poll/pull from a REST interface using AFNetworking in iOS 【发布时间】:2014-05-07 17:59:39 【问题描述】:我正在我的 iPhone 上构建一个“监控”应用程序。我正在使用 AFNetworking-2.0。我有一个后端服务器公开一个用 Python3/tornado 编写的 RESTful 接口。
根据我所处的ViewController
的级别,我想用不同的查询轮询不同的数据(应用程序的焦点调整查询的焦点)。为了“让它发挥作用”,我设置了以下内容:
#pragma mark - Pull Loop
- (void) forkPull
NSString* uri = [NSString stringWithFormat: @"%@/valves", Site.current.serialID];
[[HttpConnection current]
GET: uri
parameters: @
success:^(NSURLSessionDataTask* task, id responseObject)
[Site.current performSelectorOnMainThread: @selector(fromDoc:) withObject:responseObject waitUntilDone:YES];
NSTimeInterval delay = 60; // default poll period
// attempt to hone in if we have valid lastTouch info
if (Site.current.touched != nil)
NSDate *futureTick = [Site.current.touched dateByAddingTimeInterval: 65];
if ([futureTick compare: [NSDate date]] == NSOrderedDescending)
delay = futureTick.timeIntervalSinceNow;
[self performSelector: @selector(forkPull) withObject:nil afterDelay:delay];
NSLog(@"%@ forkPull again in %f", self, delay);
failure:^(NSURLSessionDataTask* task, NSError* error)
NSLog(@"%@ forkPull error: %@ (uri=%@)", self, error, uri);
[self performSelector: @selector(forkPull) withObject:nil afterDelay:60];
];
- (void) stopPull
[NSObject cancelPreviousPerformRequestsWithTarget: self];
#pragma mark - View Management
-(void)viewWillAppear:(BOOL)animated
[super viewWillAppear: animated];
....
[self forkPull]; // start up polling while I'm visible
-(void) viewWillDisappear:(BOOL)animated
[super viewWillDisappear:animated];
[self stopPull]; // I'm going away, so shut down the pull loop?
...
基本上,当控制器的视图出现时,它会发送一个 REST 查询(当它异步返回时,它将在 fromDoc:
方法中更新模型;控制器设置了 KVO
关系,这将导致 UI 更改。更新完成后,它可以估计下一次拉取的时间,并使用performSelector:withObject:afterDelay:
安排时间。当另一个控制器占据中心位置时,viewWillDisappear:
方法会尝试停止任何已排队的forkPull
s .
虽然这有点工作。我很确定它没有通过“Make it Right”测试。我对所有任务和后台工作的工作方式很幼稚,但在我看来AFNetworking
添加了自己的级别,所以我的stopPull
可能无效。我在NSLog
输出中看到了一些证据,其中似乎不再位于顶部的控制器仍在运行循环。
但我相信其他人以前也做过这种模式。我很想知道如何更好地架构/实现这一点。我正在寻找有人分享他们用于执行半定期 REST 查询的模式,该模式已经过审查并且运行良好。
【问题讨论】:
semi-periodic
是什么意思?想要轮询服务器多少次?
名义上,大约每分钟一次。但是每次查询都会返回一些信息,这让我可以在某种程度上调整它,以确保我轮询接近,但在服务器的下一次更新之后。
【参考方案1】:
使用 Grand Central Dispatch:
@property (strong, nonatomic) dispatch_source_t timer;
- (void)startTimer
if (!self.timer)
self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
if (self.timer)
dispatch_source_set_timer(self.timer, dispatch_walltime(NULL, 0), 60ull*NSEC_PER_SEC, 10ull*NSEC_PER_SEC);
dispatch_source_set_event_handler(_timer, ^(void)
[self tick];
);
dispatch_resume(_timer);
- (void)tick
// Do your REST query here
这将每 60 秒调用一次您的 tick
方法。
要暂停和恢复计时器,请使用 dispatch_suspend 和 dispatch_resume:
dispatch_suspend(self.timer);
dispatch_resume(self.timer);
您可以在以后的任何时间调用dispatch_source_set_timer
来提前安排时间或将它们推迟到以后:
// Fire sooner than 60 seconds, but resume 60s fires after that
unsigned long long delaySeconds = arc4random() % 60;
dispatch_source_set_timer(self.timer, dispatch_walltime(NULL, delaySeconds * NSEC_PER_SEC), 60ull*NSEC_PER_SEC, 10ull*NSEC_PER_SEC);
请参阅 Apple Concurrency Programming Guide 以获取有关此内容的完整文档。
【讨论】:
以上是关于如何在 iOS 中使用 AFNetworking 从 REST 接口定期轮询/拉取的主要内容,如果未能解决你的问题,请参考以下文章
如何在 iOS 中使用 AFNetworking 从 REST 接口定期轮询/拉取
如何使用 AFNetworking 在 iOS 目标 c 中发出此帖子请求
如何在 iOS Objective-C 中使用 AFNetworking 库下载 .json 文件?
如何在 iOS 中使用 AFNetworking 将数据发送到 php 服务器
如何允许用户在 iOS 中使用 AFNetworking 信任和固定自签名 SSL 证书
如何使用 AFNetworking 3.x 在 ios、objective-C 中使用来自 SOAP webservice 的数据