2012-08-06 46 views
1

我有一個同步過程,有時(甚至很少)需要20秒。我曾經在後臺調用選擇器。有其停止對同步完成的通知動畫進度指示器,並與它下面的代碼馬上改變:iOS上的後臺任務的UI更新

[self performSelectorInBackground:@selector(updateFunction) withObject:nil]; 

但爲了讓進度繼續我決定使用後臺任務:

UIApplication *application = [UIApplication sharedApplication]; //Get the shared application instance 

    __block UIBackgroundTaskIdentifier background_task; //Create a task object 

    background_task = [application beginBackgroundTaskWithExpirationHandler:^{ 
     [application endBackgroundTask: background_task]; //Tell the system that we are done with the tasks 
     background_task = UIBackgroundTaskInvalid; //Set the task to be invalid 

     //System will be shutting down the app at any point in time now 
    }]; 

    //Background tasks require you to use asyncrous tasks 

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
     //Perform your tasks that your application requires 

     NSLog(@"\n\nRunning in the background!\n\n"); 
     [self updateFunction]; 

     [application endBackgroundTask: background_task]; //End the task so the system knows that you are done with what you need to perform 
     background_task = UIBackgroundTaskInvalid; //Invalidate the background_task 
     NSLog(@"Finished in the background!"); 
    }); 

但是現在,當任務完成後通知被髮送(和執行),但在表中的單元格不更新,直到(有時)的時間顯著量。所以在我看來,'需求顯示'在後臺任務等等時不會被觸發,而只是在常規的刷新間隔內進行更新。

有沒有辦法讓表格單元更新使用後臺任務,或者我錯過了什麼?

編輯: 通知監聽器是:

[[NSNotificationCenter defaultCenter] addObserver:self 
             selector:@selector(refreshBttn) 
              name:@"finishedUpdate" 
              object:nil]; 

的代碼是:

- (void) refreshBttn { 
    NSLog(@"Refresh Buttun action"); 
    iDomsAppDelegate *delegate = (iDomsAppDelegate *)[[UIApplication sharedApplication] delegate]; 
    if([delegate updating]){ 
     [_updateBttn setHidden:TRUE]; 
     [_activityIndicator startAnimating];   
    } else { 
     [_updateBttn setHidden:FALSE]; 
     [_activityIndicator stopAnimating];   
    } 
    [self setNeedsDisplay]; 
    [self setNeedsLayout]; 
} 

回答

0

您需要將背景和前景線程之間的邏輯分開。您發送的通知應該從主線程發送,以便您的UI對象在收聽時可以安全地進行自我更新。所以,把updateFunction分成兩塊。也許是這樣的:

NSLog(@"\n\nRunning in the background!\n\n"); 
[self updateFunctionBackground]; 
dispatch_async(dispatch_get_main_queue(), ^{ 
    // send your notification here instead of in updateFunction 
    [[NSNotificationCenter defaultCenter] post...]; 
}); 
+0

這似乎沒有什麼區別。在這兩種情況下,我都可以看到更新單元格時創建的日誌條目,但行爲沒有變化。 (但是說了這樣的話,確實是更好,因爲它現在在主線程中執行) – 2012-08-06 17:36:11

+0

@ LuukD.Jansen也許問題出在你的UI更新代碼中?你在那裏做什麼?你可以發佈該通知的接收者的代碼嗎? – 2012-08-06 18:28:59

+0

這似乎並不是問題,因爲它只是在後臺執行更新功能時,在第一個實例中完美工作。我將把代碼,但它很簡單。 – 2012-08-07 07:04:29

2

爲了使UI更新,你必須從你的後臺調用主線程功能像這樣的線程:

[self performSelectorOnMainThread:@selector(updateFunction) withObject:nil waitUntilDone:NO]; 

如果你需要通過任何變量你可以去一個並將其添加到-withObject

+0

其實,使用[self performSelectorInBackground:@selector(updateFunction)withObject:nil];作品。我會做一些測試,看看它是否正確執行它在我測試的背景 – 2012-08-07 07:09:06

+0

,當應用程序關閉它不會繼續在後臺運行。這隻適用於直接調用更新函數(不在主線程中的後臺) – 2012-08-07 07:54:51

2

可以確保通知從你想與任何隊列......收到

[[NSNotificationCenter defaultCenter] addObserverForName:SomeNotification 
                object:sender 
                queue:operationQueue 
               usingBlock:^(NSNotification *){ 
    // Your notification will be processed in this block, and it will be 
    // received on the notification queue you specify, regardless of what 
    // thread the sender was running when the notification was posted. 
}]; 

如果你想確保它接收到主線程,你可以使用

[NSOperationQueue mainQueue] 
+0

這是一個很好的觀點,我仍然不習慣這些奇特的iOS 5 API :) – 2012-08-06 18:41:02

+0

我仍然試圖讓我的代碼4.x兼容,至少在另一個時候,因爲我確實有很多4.x用戶 – 2012-08-07 07:59:45