面白いコードが出ていた。UIイベントをトラッキングする為のライブラリ OPEventTracker。
このライブラリを使うと 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 のようにして参照できる。