7
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Xamarinで遊ぶ(3) objcの「デリゲート」とC#の「イベント」が干渉する

Last updated at Posted at 2014-08-30

←前 次→

Xamarin.iOSでUITableViewの罠 / Xamarinの進化に望む事に、C#のイベントとobjc(UIKit)のデリゲートを同時に使おうとすると罠にはまる、という記事がありました。ほうほうたしかにこれはハマりそうな所なので、実際どんな動きをしているのか確かめてみました。

TableView.WeakDelegateが切り替わってた

UITableViewControllerを継承したクラスの中
public override void ViewDidLoad ()
{
	base.ViewDidLoad ();
	Console.WriteLine ("A1 delegate == nil? {0}", (this.TableView.Delegate == null) ? "YES" : "NO");
	Console.WriteLine ("B1 weakDelegate={0}", this.TableView.WeakDelegate.GetType ());
	this.TableView.DecelerationStarted += (sender, e) => {
		Console.WriteLine ("scrolled.");
	};
	Console.WriteLine ("A2 delegate == nil? {0}", (this.TableView.Delegate == null) ? "YES" : "NO");
	Console.WriteLine ("B2 weakDelegate={0}", this.TableView.WeakDelegate.GetType ());
}

TableView.Delegateは、A1,A2共にnilでした。ですがweakDelegateはB1とB2ではオブジェクトが切り替わっています。

 A1 delegate == nil? YES
 B1 weakDelegate=MyTasky.NumberTableViewControllerController
 A2 delegate == nil? YES
 B2 weakDelegate=MonoTouch.UIKit.UIScrollView+_UIScrollViewDelegate

Xcodeで書いてる時に馴染みのあるdelegateですが、MonoTouchのUITableViewではWeakDelegateが該当しているようです。objcの弱参照だから"Weak"Delegateなのでしょう。

このWeakDelegateが、C#のイベント登録前後で切り替わっています。
推測ですが、以下の挙動をしています。

  • 初期状態では、WeakDelegateが自分自身なので、デリゲートのコールバックは自クラスとなっている。
    • なので自クラスにデリゲート部分を実装していれば、それが呼び出される。 objcのUITableViewControllerにデリゲートメソッドを書くのと同じ感覚。
  • C#のイベント登録 xxx += (sender, e) => {...} したタイミングで、WeakDelegateがC#のイベント登録されたDelegateにすり変わる。なので、自クラスのデリゲートのコールバックは呼ばれなくなる。

元の記事にある「Objective-Cとc#でのイベント実装思想の違いを把握してないと気付けなさそう」はまさにその通りですね。

ではTableView.Delegateを使ったらどうなるのか?

WeakDelegateとDelegateがあるので、じゃあDelegateを使ったらどうなるか?と試したのですが、WeakDelegateの時と同じで、片方が片方を隠してしまいました。

  • TableView.Delegate を登録してから C#のイベント を登録 → C#のイベントが有効
  • C#のイベント を登録してから TableView.Delegate を登録 → Delegateのイベントが有効

混ぜるな危険って事なんですね。

この手の罠一覧が欲しい

「この先地雷原」が分かる、地図のような資料があれば、まず見ておきたい所です。

その他メモ書き

  • objcのUIKitとMonoTouchのUIKitの、メソッド対応表というか「命名規則変換ルール」が欲しい。
    • objcの"will〜"はMonoの"〜Started"とか。
  • C#のイベント登録 +=(){} はまだよく分からない。
  • XamarinStudioで、「このクラスのAPIリファレンス」を表示するショートカットキーは何所だ。
  • XamarinStudioで日本語入力していると、変換直後のキー入力1個欠落してるみたい→コメントに日本語書いてると変になるのだけど、自分だけかな?
7
7
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?