統計情報(30日間)


最新情報をツイート


人気の投稿

UIのイベントが発生していない時に重い処理を

このエントリーをはてなブックマークに追加

面白いコードが出ていた。UIイベントをトラッキングする為のライブラリ OPEventTracker。

ライブラリというには小さなコード(1クラス、1桁のメソッド)が状況によっては非常に有用かもしれない。

このライブラリを使うと UIイベント(ユーザが指でスクロールを開始したなど)をトラッキングして、用意されたプロパティでチェックすることができる。
if ([[OPEventTracker sharedTracker] isTracking])
{
  // do something
}
通知も用意されている。
OPEventTrackerNotifications.started
OPEventTrackerNotifications.stopped

ユーザが指で何か操作している時、たとえばスクロールしている時にメインスレッドでそこそこの処理を走らせると、ひっかかりが起きるなどの影響がでる。UIへ影響を与える処理は通常は別スレッドで行うのが定石だが、それでもメインスレッドでしかできない処理もある。そんな時にこれを使うとユーザが操作していないタイミングを見計らって処理を実行することが出来るため、UIへの影響を最小限に抑えることができる。

作者は別スレッドで NSManagedObjectContext を保存し、メインスレッドのコンテキストにマージするタイミングを計るのに使っているとのこと。


試しに簡単なアプリを作って試してみた。
UITextView を一つ用意し、先程の通知がどんな時に送られるのかを見てみる。
- (void)eventsStarted
{
    NSLog(@"%s|%@", __PRETTY_FUNCTION__, nil);
}

- (void)eventsStopped
{
    NSLog(@"%s|%@", __PRETTY_FUNCTION__, nil);
}

- (void)viewDidLoad
{
    [OPEventTracker startTracking];
    [super viewDidLoad];
    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(eventsStarted) 
                                                 name:OPEventTrackerNotifications.started 
                                               object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(eventsStopped) 
                                                 name:OPEventTrackerNotifications.stopped
                                               object:nil];
}

実機で確認するとログはこんな感じ:
-[ViewController eventsStopped]|(null) ← 実行開始直後
-[ViewController eventsStarted]|(null) ← テキストをスクロール開始直後。その後は指をつけたままグリグリ。
-[ViewController eventsStopped]|(null) ← 指を離してバウンスが完了した後


あと直接は関係ないが、通知を表現するのに構造体を使っている。これもユニーク。
OPEventTracker.h
extern const struct OPEventTrackerNotifications {
    __unsafe_unretained NSString *started;
    __unsafe_unretained NSString *stopped;
} OPEventTrackerNotifications;

OPEventTracker.m
const struct OPEventTrackerNotifications OPEventTrackerNotifications = {
 .started = @"OPEventTrackerNotificationStarted",
 .stopped = @"OPEventTrackerNotificationStopped",
};
こうすると OPEventTrackerNotifications.started のようにして参照できる。


Leave a Reply