我想使用dispatch_async偶尔从我的Web服务器中提取不断变化的资源(大约每60秒)。
我想使用dispatch_async,但我想给它一个函数名。因为我想让这个功能睡觉并重新做同样的事情。
这就是我要做的事情dispatch_async(self.downloadQueue, @selector(getDataThread:));
(这不会编译)
我认为while循环不是一个好主意,所以我想知道什么是最好的方法
答案 0 :(得分:4)
有几点意见:
如果要为调度的操作创建计时器,请创建dispatch_source_t
类型DISPATCH_SOURCE_TYPE_TIMER
,例如,定义两个类属性:
@property (nonatomic, strong) dispatch_queue_t queue;
@property (nonatomic, strong) dispatch_source_t timer;
然后创建计时器:
- (void)createTimer
{
self.queue = dispatch_queue_create("com.stackoverflow.16782529", 0);
self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, self.queue);
if (self.timer)
{
dispatch_source_set_timer(self.timer,
dispatch_walltime(NULL, 0),
60ull * NSEC_PER_SEC,
1ull * NSEC_PER_SEC);
dispatch_source_set_event_handler(self.timer, ^{
NSLog(@"doing something");
});
dispatch_resume(self.timer);
}
}
顺便说一句,就像所有重复的计时器一样,在viewDidAppear
中创建并删除viewDidDisappear
中可能是一种好习惯:
- (void)viewDidAppear:(BOOL)animated
{
[self createTimer];
}
- (void)viewDidDisappear:(BOOL)animated
{
dispatch_source_cancel(self.timer);
}
如果您不想使用块,请使用_f
等效的任何GCD功能。所有采用块的GCD函数都有一个带有C函数的再现(后缀为_f
)。例如,使用上面的示例,非块再现将如下所示:
- (void)createTimer
{
self.queue = dispatch_queue_create("com.stackoverflow.16782529", 0);
self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, self.queue);
if (self.timer)
{
dispatch_source_set_timer(self.timer,
dispatch_walltime(NULL, 0),
60ull * NSEC_PER_SEC,
1ull * NSEC_PER_SEC);
dispatch_source_set_event_handler_f(self.timer, &myTimerHandler);
dispatch_resume(self.timer);
}
}
void myTimerHandler(void *context)
{
NSLog(@"doing something");
}
如果你宁愿使用NSTimer
(使用Objective-C方法而不是C函数),你可能会有以下属性:
@property (nonatomic, strong) dispatch_queue_t queue;
@property (nonatomic, strong) NSTimer *timer;
然后在视图出现时创建计时器,并在它消失时将其删除:
- (void)viewDidAppear:(BOOL)animated
{
self.queue = dispatch_queue_create("com.stackoverflow.16782529", 0);
self.timer = [NSTimer scheduledTimerWithTimeInterval:60.0 target:self selector:@selector(handleTimer:) userInfo:nil repeats:YES];
}
- (void)viewDidDisappear:(BOOL)animated
{
[self.timer invalidate];
}
- (void)handleTimer:(NSTimer *)timer
{
dispatch_async(self.queue, ^{
NSLog(@"doing something");
});
}
就个人而言,如果您经常对此进行检查,那么拉动架构(您每隔60秒不断向下拉数据)可能就没有意义了。您可以考虑打开服务器的套接字并让服务器在有数据更新时通知您(请参阅此Ray Wenderlich example),或使用推送通知(notifications documents谈论本地通知和推送通知,但对于此应用程序,您正在查看推送通知)。显然,这些都需要更多的服务器开发,但它在架构上更优雅/更有效。
顺便说一下,如果您要每隔60秒触发一次网络事件,如果您要异步启动网络活动(通过#3的NSTimer
方法,或者如果您的网络请求本身是异步运行的)您可能还需要引入一些检查以确保先前的请求已经完成,然后再启动另一个请求。它不太可能没有,但你应该检查这一点。如果您使用dispatch_source_create
方法并使用同步网络请求,这不是一个问题(因为计时器不会被重新触发,直到前一个完成),否则,您可能想要请注意,不要因网络请求而备份队列。
答案 1 :(得分:0)
怎么样......
NSTimer *timer = [NSTimer timerWithTimeInterval:60 target:self selector:@selector(getDataThread:) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
- (void)getDataThread:(id)foo {
dispatch_async(self.downloadQueue, ^{
// code you want to run asynchronously
});
}
似乎你想要一些代码块以异步方式运行......但你希望它也能以一个定时间隔运行,所以我认为这应该足够了。
如果您想完全放弃阻止和dispatch_async
,可以查看NSOperationQueue
,请记住NSOperationQueue
是建立在GCD上的,但您无需担心与它接口直接