2009-07-29 5 views
1

セグメント化されたコントロールがトグルとして使用されています。トグルすると、目立った時間がかかります(テーブルビューのセクションの挿入/削除、変更のアニメーション化など)。私は、セグメント化されたコントロールがすぐに選択に応答するようにしたい。だから、セグメント化されたコントロールのUIControlEventValueChangedイベントのコードを処理し、私の行動に、私は、次の手順を実行しますUISegmentedControl(その他)の応答性を維持する

updateGroupingがある
- (IBAction)groupingChanged:(id)sender { 
    UISegmentedControl *seg = sender; 
    [tableModel toggleOn:[seg selectedSegmentIndex] == ToggleOnIndex]; 
    [self performSelectorOnMainThread:@selector(updateGrouping) 
          withObject:nil 
         waitUntilDone:NO]; 
} 

waitUntilDone:NOの設定

- (void)updateGrouping { 
    MXAssertMainThread(); 

    [tableView beginUpdates]; 
    ... several table updates 
    [tableView endUpdates]; 
} 

は、updateGroupingが呼び出される前に完了するgroupingChanged方法を可能にしかし、これはビューを再描画するのに十分ではないようです。セグメント化されたコントロールは、テーブルの更新が完了するまでスティックされ、切り替えられます。

だから私はそうのような更新のためにスレッドを作成するgroupingChanged:を修正しようとした:

- (void)delayed { 
    [self performSelectorOnMainThread:@selector(updateGrouping) 
          withObject:nil 
         waitUntilDone:NO]; 
} 

- (IBAction)groupingChanged:(id)sender { 
    UISegmentedControl *seg = sender; 
    [tableModel toggleOn:[seg selectedSegmentIndex] == ToggleOnIndex]; 
    [self performSelectorInBackground:@selector(delayed) withObject:nil]; 
} 

そして、これは作業を行います。セグメント化されたコントロールは即座にトグルし、すぐに表が続きます。しかし、私は結果に自信がありません。新しいスレッドが起動している間、メインスレッドに執行猶予を与えるだけの副作用ですか?これはUIに更新をキューイングする必要があるのでしょうか?それは明らかにハッキーです。私は誰かがこの状況のた​​めに従っているより良いパターンを持っていることを望んでいます。

答えて

1

セグメント化されたコントロールが本当に素早く再描画されるようにしたいのであれば、おそらくスレッドに潜んでいるとは限りません。

代わりに、私はちょうど0.1のような低い値のタイマーを設定し、ユーザーに目立つ遅延なしにコントロールを更新させるのに十分なはずです。

多くの作業が必要だが、すばやいUIアップデートが必要な場合は、これを使用しました。

まだ少し「ハッキー」ですが、スレッドの導入はありません。

だから... ...このようそれの

- (IBAction)groupingChanged:(id)sender { 
    UISegmentedControl *seg = sender; 
    [tableModel toggleOn:[seg selectedSegmentIndex] == ToggleOnIndex]; 
    [NSTimer scheduledTimerWithTimeInterval:0.1 
            target:self 
            selector:@selector(updateGrouping) 
            userInfo:nil 
            repeats:NO];  

} 
+0

これは中間スレッドを排除するので改善ですが、一般的な非ハッキーパターンはないと信じることを拒否します。 –

+0

performSelector:withObject:afterDelayもKendallが指摘するように有効です。この問題は、UIを更新できるように実行ループを完了する必要があることです。これは実際にハックではなく、この事実を認めているだけです。メインスレッドがそのコースを実行することを許可せずにUIを更新する方法はわかりません。 –

+0

もちろん、私はその原因を理解しています。私はこれのための共通のパターンを望んでいたと思います。クレジットが獲得(遅れている)。 –

2

考える - あなたが行うすべてのものは、一般的にUIの更新を含め、メインスレッドで実行されます。

元のコードでは、セグメントのUI更新を行ったコードよりも前にテーブルビューを更新したコードに達しました。

したがって、バックグラウンドスレッドがテーブルの更新を処理している間にメインスレッドがUI更新を完了することが許可されているため、メインスレッドに休憩を与えるとUIの更新を完了するまでに時間がかかりました。

performSelector:withObject:afterDelayを0.0の遅延で使用する方法もあります(セレクタに進む前にメインスレッドが他のものを処理できるようにする)。 performSelectorOnMainThreadがそうでなかった場所では動作しますが、そのような呼び出しは非常に似たようなことをやっても即座になる可能性があります。

0

私は同じ問題にぶつかり、UISegmentedControlをサブクラス化して遅延UISegmentedControlを作成して解決しました。

遅延制御では、addTarget:action:forControlEvents:をオーバーライドしてターゲット&の動作をキャプチャします。セグメントイベントが発生したら、私はNSTimerを実行して、キャプチャされたターゲット&のアクションを設定された遅延の後に起動します。あなたは、私がgoogle code上でそれをオープンソース化しましたコントロールをダウンロードする

// Follows all normal initialization patterns of UISegmentedControl 
UISegmentedControl *segmentedControl = [[DelayedUISegmentedControl alloc] 
    initWithItems:[NSArray arrayWithObjects: @"First", @"Second", nil]]; 

// Adds a delay to the selector; default is 0.25 
[segmentedControl addTarget:self action:@selector(segmentAction:) 
    forControlEvents:UIControlEventValueChanged]; 

たい場合:結果がクリックされたと私はUISegmentedControlしまうように私はDelayedUISegmentedControlを使用することができますUIがセグメントを表示するように更新されるということです。

関連する問題