在 iOS 中定期在后台线程中运行任务

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25939073/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 02:38:24  来源:igfitidea点击:

Running a task in background thread periodically in iOS

iosobjective-cmultithreadingbackground-process

提问by NTNT

I'm a new in iOS. I'm working on the app needs to run a task for getting data from Server in the background thread as i don't want to lock the UI in main thread. This task will take a long time, I tried using the NSTimer but it is still lock the UI. My task is to check new messages in Chat screen, I need to call this task every 5s. If I use NSTimer, when input text , the text seems to freeze a moment while this task is performing. Is there any way to process this task without lock UI. Please give me some advices. Thanks so much.

我是 iOS 新手。我正在开发应用程序需要运行一个任务,以便在后台线程中从服务器获取数据,因为我不想在主线程中锁定 UI。这个任务需要很长时间,我尝试使用 NSTimer 但它仍然锁定 UI。我的任务是在聊天屏幕中检查新消息,我需要每 5 秒调用一次此任务。如果我使用 NSTimer,当输入文本时,文本在执行此任务时似乎会冻结片刻。有没有办法在不锁定 UI 的情况下处理此任务。请给我一些建议。非常感谢。

== UPDATE CODE ==

== 更新代码 ==

 - (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];
            }

        });
    });
}

回答by Stavash

Scheduling the task using an NSTimer is indeed the right way to go. You just need to make sure you're running your heavy non-UI code on a background thread. Here's an example

使用 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
        });
    });
}

回答by dmerlea

dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
    //Background Thread
    dispatch_async(dispatch_get_main_queue(), ^(void){
        //Run UI Updates
    });
});

Try this

尝试这个