JavaScriptでユーザからのイベントを受け取ってホゲホゲ、という処理は大体次のようなスタイルで書く。なお、jQueryとか使っていても概要は同じ。
el.addEventListener("eventName", function(evt) { // do something }, false);
iOS appでこのようなイベントハンドーリング的処理を行う場合、基本的にはdelegateを使う。
-(id)init { self = [super init]; if ( self != nil ) { Foo* foo = [[Foo alloc] init]; foo.delegate = self; Bar* bar = [[Bar alloc] initWithsomething:nil target:self selector:@selector(didReceiveBarsEvent)]; } } -(void)didReceiveFoosEvent { // do something } -(void)didReceiveBarsEvent { // do something }
Android appでこのような処理を行う場合、基本的にはなんとかEventListenerを使う。
view.setOnClickListener(new View.OnClickListener() { @override public void onClick(View view) { } });
これらでもまあ悪くはないのだが、
という問題があるので、それぞれについてJavaScriptのようにさらっと書くための方法をしるす。ちなみに、一番上で示したようなスタイルで書くのが常に便利だ・よい、といっているわけではない。
iOS
iOS4.0以降ならBlock(Objective-Cにおける、いわゆる無名関数)が使える。が、iOS標準のUIKitにはBlockを受け取ってdelegateに実装されたメソッドとみなす、というようなインタフェースがないので(多分)、BlocksKitを使う。
そうすると、それっぽい記述が出来るようになる。実はまだ試してない。
Android
Javaをやめて、Scalaを使う。基本的にネイティブアプリを別言語で書く系のソリューションは地雷が多いので利用には慎重になるべきですが、Scala on Androidはこれ↓
が大分レールをしいてくれるので、あまり悲しいことにはなりません。
で、その上で以下のようなImplicit Conversionを書いてよみこむ。ちなみにこれは僕が考えついたのではなく、パクリです。
object ViewConversions { implicit def toClickListener(bt: Button) : ButtonViewConversions = { new ButtonViewConversions(bt) } } class ButtonViewConversions(bt: Button) { type F = (View) => Unit def onClick(f: F): Unit = { bt.setOnClickListener( new View.OnClickListener() { override def onClick(v: View) = { f(v) } } ) } }
と、このように書けるようになる
val button = findView(TR.button1) button.onClick { v => // do something }
まとめ
このような方法は存在しますが、イベントハンドラが長くなる場合はちゃんと名前のある関数にするなどした方が無難でしょう。