2012-03-02 151 views
0

我已經閱讀了所有我能找到的相關問題,但仍然卡住了,所以我希望有人能夠發現我的推理錯誤。即使更新從主線程調用,UI也不會更新

我想定期更新一些UIView。爲了簡單起見,我將代碼縮減爲下面的代碼。總結:在viewDidLoad中,我調用了一個新的後臺線程方法。該方法在應該更新某個UILabel的主線程上調用一個方法。代碼似乎正常工作:後臺線程不是主線程,調用UILabel更新的方法在主線程上。在代碼:

在viewDidLoad中:

[self performSelectorInBackground:@selector(updateMeters) withObject:self]; 

這將創建一個新的後臺線程。我的方法updateMeters(爲簡單起見),現在看起來是這樣的:

if ([NSThread isMainThread]) { //this evaluates to FALSE, as it's supposed to 
    NSLog(@"Running on main, that's wrong!"); 
} 
while (i < 10) { 
    [self performSelectorOnMainThread:@selector(updateUI) withObject:nil waitUntilDone:NO]; 
//The code below yields the same result 
//  dispatch_async(dispatch_get_main_queue(), ^{ 
//   [self updateUI]; 
//  }); 
    [NSThread sleepForTimeInterval: 1.05]; 
    ++i; 
} 

最後,updateUI做到了這一點:

if ([NSThread isMainThread]) { //Evaluates to TRUE; it's indeed on the main thread! 
    NSLog(@"main thread!"); 
} else { 
    NSLog(@"not main thread!"); 
} 
NSLog(@"%f", someTimeDependentValue); //logs the value I want to update to the screen 
label.text = [NSString stringWithFormat:@"%f", someTimeDependentValue]; //does not update 

據我所知,這應該工作。但它不,不幸的是...註釋掉dispatch_async()產生相同的結果。

+0

什麼是「someTimeDependentValue」?一個浮點數我想.. – 2012-03-02 15:26:31

+1

你試過用NSTimer嗎?也許在viewDidLoad中,你啓動了一個NSTimer。打勾時,讓它執行你的UI更新。在單個視圖中使用2個獨立的自引用過程有點令人困惑。 – Jeremy 2012-03-02 15:27:12

+0

@RaphaelAyres是的。 – Tom 2012-03-02 15:40:11

回答

1

很可能你的格式聲明錯誤。

label.text = [NSString stringWithFormat:@"%f", someTimeDependentValue]; 

確保someTimeDependentValue是一個浮點數。如果它是一個整數,它可能會被格式化爲0.0000。

Here's a repo顯示您描述的工作版本。無論什麼錯誤都與線程無關。

+0

換句話說,你是說我的代碼正如我在我的問題中列出的那樣應該工作? – Tom 2012-03-02 16:13:18

+0

它正在回購。我幾乎只是將你的代碼複製並粘貼到UIViewController的一個子類中。我碰到的唯一障礙是我最初將tdv(我創建的一個實例變量替換someTimeDependentValue)聲明爲int,因爲我沒有注意到你的stringWithFormat是要求float/double。 – 2012-03-02 16:16:15

+0

這很奇怪。我在該方法中也有一個'NSLog()',這就是打印(更新)值。所以我非常確定的一件事是格式聲明是正確的,我提供的價值也是正確的。我會更新我的問題以反映這一點。 – Tom 2012-03-02 16:20:17

0

爲了擴大對我的評論,下面是可能使用的NSTimer,從而實現最佳的場景:

-(void)viewDidLoad 
{ 
     NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:<number of seconds per tick> target:self selector:@selector(timerTick:) userInfo:nil repeats:YES]; 
} 

-(void)timerTick:(id)sender 
{ 
     label.text = ...; 
} 

還有一個更復雜的方法,我在我的項目中被廣泛使用。這就是引擎的概念。

我會有一個引擎,使用計時器在後臺運行。在關鍵時刻,它會使用dispatch_async/dispatch_get_main_thread()在主線程上發佈通知NSNotificationCenter,然後您的任何一個視圖都可以通過更新其UI來訂閱和處理該通知。