今日はRubyMotionでGCD(Grand Central Dispatch)を使う話です.
GCD とは
GCDというのは,
非常に効率的なシステム機能と使い勝手のよいプログラミングモデルを併用して,マルチプロセッサを最大限に活用するために必要なコードを徹底的に簡素化
するものらしいです
(AppleのGrand Central Dispatchの説明より)
UITableViewとかそういうのはMainThreadでちょっと重い処理をすると,すぐにパフォーマンスが悪くなってなんだこのアプリ糞だな!とか言われるので,そういう時には別Threadを立ててMainThreadの処理を邪魔しないように処理を行う必要があります.
それを楽にしてくれるのがGCD.
Objective-C
Obj-Cのコードだと,
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
// 処理
});
こんな感じになります.
RubyMotion
RubyMotionでは,GCD関連はDispatch
クラスを使います.
RubyMotion Runtime Guid にも書いてます.
上で書いたObj-CのコードをRubyMotionで書きなおすと,
Dispatch::Queue.concurrent.async{
# 処理
}
こうなります.超簡単.
UIの更新に関して
さて,実際にはConcurrent Dispatch Queueで時間のかかる処理を行い,
処理を行った結果をUIに反映させることがよくあります.
その場合に直接UIへ値を代入とかすると落ちます.
UIはMainThreadから更新しなければなりません.
その場合は,
Dispatch::Queue.concurrent.async{
# 処理
Dispatch::Queue.main.async{
#UI更新
}
}
このようにDispatch::Queue.main
でMain Dispatch Queueに更新処理を入れることで実現できます.
実戦
実際に少し書いてみます.
$ motion create gcd
$ cd gcd
app/app_delegate.rb
class AppDelegate
def application(application, didFinishLaunchingWithOptions:launchOptions)
@window = UIWindow.alloc.initWithFrame UIScreen.mainScreen.bounds
@window.rootViewController = NSBundle.mainBundle.loadNibNamed(
'RootViewController',
owner: self,
options: nil).first
@window.rootViewController.wantsFullScreenLayout = true
@window.makeKeyAndVisible
true
end
end
InterfaceBuilder
resouces/RootViewController.xib
という形でUIButton(Tag 2),UILabel(Tag 1)を追加しておいて下さい.
(参考:[RUBYMOTION] INTERFACEBUILDERと合わせて使って楽をしよう)
app/root_view_controller.rb
class RootViewController < UIViewController
def viewDidLoad
@label = view.viewWithTag 1
@button = view.viewWithTag 2
@button.addTarget(
self,
action: 'onClicked:',
forControlEvents:UIControlEventTouchUpInside)
end
def onClicked(sender)
p "onClicked"
Dispatch::Queue.concurrent.async {
NSThread.sleepForTimeInterval 5
Dispatch::Queue.main.async {
@label.text = ["hoge", "fuga", "moge"].sample
}
}
end
end
実行
$ rake
シミュレータが立ち上がり,Buttonを押すとLabelの文字列がちょっと待ったあとに変わります.
連打すると次々変わると思います.
その間Buttonが押せないとかそういうことが起こらないのが分かると思います.