在 iOS 中定期在后台线程中运行任务
Posted
技术标签:
【中文标题】在 iOS 中定期在后台线程中运行任务【英文标题】:Running a task in background thread periodically in iOS 【发布时间】:2014-09-19 17:08:14 【问题描述】:我是 ios 新手。我正在开发应用程序,需要在后台线程中运行从服务器获取数据的任务,因为我不想将 UI 锁定在主线程中。这个任务需要很长时间,我尝试使用 NSTimer 但它仍然锁定 UI。我的任务是在聊天屏幕中查看新消息,我需要每 5 秒调用一次此任务。如果我使用 NSTimer,当输入 text 时,文本似乎在执行此任务时冻结了片刻。有什么方法可以在不锁定 UI 的情况下处理此任务。请给我一些建议。非常感谢。
== 更新代码 ==
- (void)performBackgroundTask
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
//Do background work
if([[NSUserDefaults standardUserDefaults] boolForKey:@"LoggedIn"])
NSDictionary * userDictionary = [[NSUserDefaults standardUserDefaults] dictionaryForKey:@"SessionDictionary"];
NSString *authenKey= [userDictionary valueForKey:@"authToken"];
NSString* limit = @"1000";
[[LSDataManager sharedDataManager] getLatestMessagesWithAuthKey:authenKey andLimit:limit withBlock:^ (NSDictionary* responseDict)
if (responseDict)
[self loadDataFromServer:responseDict];
NSArray* lastMessageArray= nil;
//filter message data
if (self.MessagesArray.count >0)
if (!self.isSeller)
lastMessageArray = [self filterMessageData:self.MessagesArray withProductID:self.productID withSellerID:self.receiverID withBuyerID:self.senderID];
else
lastMessageArray = [self filterMessageData:self.MessagesArray withProductID:self.productID withSellerID:self.senderID withBuyerID:self.receiverID];
NSLog(@"filter array %@",lastMessageArray);
if([lastMessageArray count] >0)
//[self loadMessages:lastMessageArray];
if (self.TempdataSource == nil)
self.TempdataSource = [NSMutableArray array];
else
[self.TempdataSource removeAllObjects];
self.TempdataSource = [[[ContentManager sharedManager] generateConversation:lastMessageArray withSenderID:self.senderID] mutableCopy];
];
dispatch_async(dispatch_get_main_queue(), ^
//Update UI
//compare 2 arrays
if ([self.TempdataSource count] == [self.dataSource count])
NSLog(@"both are same");
else
NSLog(@"both are different");
self.dataSource = [self.TempdataSource mutableCopy];
[self refreshMessages];
);
);
【问题讨论】:
对不起。对于你的问题,我无法给你答案。但我只能说使用 NSTimer 每 5 秒调用一次任务是消耗资源的,我不建议你这样做! @eliasah:谢谢。你有什么比它更好的解决方案吗? @eliasah 我不确定你为什么认为 NSTimer 是资源密集型的。你有参考吗?还是您只是指每 5 秒做一次的想法? 我知道这篇文章已经过时了,但你设法解决了这个问题吗? 【参考方案1】:使用 NSTimer 调度任务确实是正确的方法。您只需要确保在后台线程上运行繁重的非 UI 代码。这是一个例子
- (void)viewDidLoad
[super viewDidLoad];
[self startTimedTask];
- (void)startTimedTask
NSTimer *fiveSecondTimer = [NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:@selector(performBackgroundTask) userInfo:nil repeats:YES];
- (void)performBackgroundTask
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
//Do background work
dispatch_async(dispatch_get_main_queue(), ^
//Update UI
);
);
【讨论】:
谢谢,但我听说如果使用 NSTimer 不好,对吧?对不起,我是IOS新手,我只是想了解更多 你能添加一个你在哪里听过这个的参考吗? @Stavash 我说过 NSTimer 来激活任务是消耗资源的。我没说不好。但我完全同意你给 +1 的解决方案。 只要你使用得当,它就是适合工作的课程。请记住,它需要安排在主运行循环上,并且它保持对其目标(在本例中为 self)的强引用。 @Stavash:我能问个问题吗?如果我想在所有应用程序的后台线程中运行此任务。我的意思是即使任何 Viewcontroller 处于活动状态,此任务仍在运行【参考方案2】:dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void)
//Background Thread
dispatch_async(dispatch_get_main_queue(), ^(void)
//Run UI Updates
);
);
试试这个
【讨论】:
感谢您的快速回复。我试过了,还是一样以上是关于在 iOS 中定期在后台线程中运行任务的主要内容,如果未能解决你的问题,请参考以下文章