在iPhone App编码中,我需要并行完成几项任务:
第1部分:始终(即使应用程序当前未处于活动状态): 从远程数据库中获取一些数据并将其保存在本地Sqlite中 为此,我在AppDelegate的单独队列中触发NSTimer,如下所示:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
...
...
self.queueForDbFetch = dispatch_queue_create("queueForDbFetch", NULL);
self.queueForDbFetchTimer = dispatch_queue_create("queueForDbFetchTimer", NULL);
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(getDbData:) name:kNotif_GetDbData object:nil];
dispatch_async(self.queueForDbFetchTimer, ^(void) {
self.timerDbNotifier = [NSTimer scheduledTimerWithTimeInterval:60.0
target:self selector:@selector(scheduleNotificationToFetchDbData)
userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:self.timerDbNotifier forMode:NSDefaultRunLoopMode];
});
...
...
}
第2部分:
然后,我需要使用获取的数据(来自本地sqlite数据库)异步更新UI,这与队列&在UIViewController类中这样的定时器(类似于上面的):
-(void) initializeThisView {
// Make sure the queues are created only once
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
self.queueForUiRefresh = dispatch_queue_create("queueForUiRefresh", NULL);
self.queueForUiRefreshTimer = dispatch_queue_create("queueForUiRefreshTimer", NULL);
});
[self scheduleUiDataRefresher];
}
-(void) scheduleUiDataRefresher {
dispatch_async(self.queueForUiRefreshTimer, ^(void) {
self.timerUiDataRefresh = [NSTimer scheduledTimerWithTimeInterval:60.0
target:self selector:@selector(loadUiData)
userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:self.timerUiDataRefresh forMode:NSDefaultRunLoopMode];
});
}
-(void) loadUiData {
dispatch_async(self.queueForUiRefresh, ^(void) {
[self refreshWithUiData:dict];
});
}
问题:
NSTimer实例(在第1部分和第2部分中)被触发一次,就是这样。他们不重复。 1.会创建NSTimer在主队列中重复其他用户与App的交互吗? 2.我的活动结构是否有任何问题(或更好的方法)?
答案 0 :(得分:2)
不要在dispatch_async()调用中创建计时器。一旦传递给dispatch_async()的块已经完成运行(并且它在创建定时器后直接完成),所有属于它的数据都将被释放。我很惊讶它没有崩溃。此外,当您使用scheduledTimerWithTimeInterval:target:selector:userInfo:重复时,计时器将已安排到主runloop。对NSRunLoop:addTimer:的调用不是必需的,它将无效或者在调度计时器时会发生冲突。
回答你的问题:
创建没有dispatch_async()的计时器,只需直接调用NSTimer:scheduledTimerWithTimeInterval :.不要使用NSRunLoop:addTimer(除非你确切地知道为什么要这样)。然后在您的计时器调用的选择器中,使用dispatch_async()来启动异步任务。
但是,如果您确定这些任务不会花费很长时间,那么您也可以完全避免使用dispatch_async()。