2012-03-02 10 views
0

関連するすべての質問を読みましたが、私はまだ立ち往生しています。メインスレッドから更新が呼び出されてもUIが更新されない

私はUIViewを定期的に更新しようとしています。簡単にするために、私はコードを以下のものに減らしました。要約:viewDidLoadでは、新しいバックグラウンドスレッドでメソッドを呼び出します。そのメソッドは、UILabelを更新するはずのメインスレッド上のメソッドを呼び出します。コードは正しく動作しているようです:バックグラウンドスレッドはメインスレッドではなく、UILabel更新を呼び出すメソッドはメインスレッド上にあります。コードでは:のviewDidLoadで

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

これは新しいバックグラウンドスレッドを作成します。

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 

、これは動作するはずです(簡単にするために)私の方法のupdateMetersは、次のようになります。しかし、それは残念なことに... dispatch_async()のコメントは同じ結果をもたらしません。

+0

「someTimeDependentValue」とは何ですか?私が思う浮動小数点。 –

+1

NSTimerを使ってみましたか?おそらく、viewDidLoadでは、NSTimerを起動します。チックでは、あなたのUIの更新を実行してください。 2つの独立した自己参照プロセスを1つのビューで使用すると、少し混乱することがあります。 – Jeremy

+0

@RaphaelAyresはい。 – Tom

答えて

1

ほとんどの場合、フォーマットステートメントが間違っている可能性があります。

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

someTimeDependentValueがfloatであることを確認してください。それがintの場合、それはおそらく0.0000にフォーマットされます。

Here's a repoは、あなたが記述しているものの作業バージョンを示しています。何が間違っていても、スレッドには関係しません。私のコメントに拡大すること

+0

言い換えれば、私の質問に列挙した私のコードはうまくいくはずですか? – Tom

+0

それはそのレポで働いています。私はちょうどコピーし、あなたのコードをUIViewControllerのサブクラスに貼り付けました。私がヒットした唯一の問題は、stringWithFormatがfloat/doubleを要求していることに気付かなかったため、当初tdv(someTimeDependentValueを置き換えるために作成したインスタンス変数)をintとして宣言したことでした。 –

+0

それは変です。私はメソッド内に 'NSLog()'も持っており、それは(更新)値を出力しています。だから私がかなり確信していることは、フォーマットステートメントが正しいことと、私が提供する値が正しいことです。私はそれを反映するために私の質問を更新します。 – Tom

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を更新してその通知を処理できます。