2015年3月26日木曜日

処理を一定時間止める

同期処理で、一定時間処理を待たせたり、数秒間何かを表示してから消すとかそういう時に使える。

以下2秒間処理停止させる書き方をいくつか。

NSThreadを使う方法

‪Objective-C‬

[NSThread sleepForTimeInterval:2.0f];

Swift3

NSThread.sleepForTimeInterval(2.0)

Swift4

Thread.sleep(forTimeInterval: 2.0)

sleep関数を使う方法

sleep(2);
でも同じことができる。こっちはC言語の関数なんだろう。
上の2つは結果は一緒みたいで、画面更新まで止まるようだ。直前に書き換えた画面は停止が明けないと更新されない。
処理的にはどっちでもいいんだろうけど、NSThread使ったほうがiOS的には推奨だったりするのかな?

NSRunLoopを使う方法

‪Objective-C

[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:2.0f]];

Swift3

NSRunLoop().runUntilDate(NSDate(timeIntervalSinceNow: 2.0))

Swift4

RunLoop.current.run(until: Date.init(timeIntervalSinceNow: 2.0))

NSRunLoopってのは要するにアプリのバックで回り続けてる入出力とかの監視をしてるプロセスのようだ。よくわかってないけど。
こっちは画面更新は止まらないので、直前に書き換えたものをちゃんと表示してくれる。
逆に、書いた部分のコードの進行以外は実行されちゃうようなので、注意。

直前の画面書き換えを反映させてから処理を停止させる方法

画面更新はOSが定期的(数十分の1秒ごととか)にUIViewのdrawRectメソッドを実行することで行われるので、画面書き換え(ラベルのテキスト変更とかも)処理直後に[NSThread sleepForTimeInterval:2.0f];なんて呼ぶと更新される間もなく停止されちゃうのだね。

だから、
_label.text = @"hogehoge";
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.05f]];
で画面更新のタイミング分コードの進行を待たせた後に
[NSThread sleepForTimeInterval:2.0f];
で処理を停止させてやればいいのだね。
めんどっちーけど。

なお、
[NSThread sleepForTimeInterval:2.0f];
を使った停止中でも、画面をいじるとその操作がバッファされてるようで、停止明けに実行されちゃったりするので、ボタンとかをイネーブルにするなど、別途対策を取られたし。

0 件のコメント:

コメントを投稿