それぞれに関連付けられたインターフェイスとプレゼンターを備えた多数のビューで構成される MonoTouch アプリがあります。次のようになります。
class SomeView : UIView, ISomeView
{
public event EventHandler PreviousClicked = delegate {};
public event EventHandler NextClicked = delegate {};
public event EventHandler Loaded = delegate {};
public SomeView()
{
new SomePresenter(this);
}
}
interface ISomeView
{
event EventHandler PreviousClicked;
event EventHandler NextClicked;
event EventHandler Loaded;
event EventHandler Unloaded;
}
class SomePresenter
{
readonly ISomeView _view;
public SomePresenter(ISomeView view)
{
_view = view;
_view.Loaded += Loaded;
_view.NextClicked += NextClicked;
_view.PreviousClicked += PreviousClicked;
_view.Unloaded += Unloaded;
}
void Loaded (object sender, EventArgs e)
{
//Nothing special
}
void PreviousClicked (object sender, EventArgs e)
{
//Nothing special
}
void NextClicked (object sender, EventArgs e)
{
//Nothing special
}
}
このコードはシミュレーターでは完全に機能しますが、iPad で実行すると、プレゼンターがコンストラクターでビューにイベントをアタッチするとクラッシュします。しかし、それは非常に奇妙な方法でクラッシュします。
まず、最初のイベントをアタッチしてもクラッシュしませんが、2 番目のイベントをアタッチするとクラッシュします。
_view = view;
_view.Loaded += Loaded;
_view.NextClicked += NextClicked; //FAILS HERE
返されるスタックトレースは
0 SomeApp 0x008f8e01 mono_handle_native_sigsegv + 244
1 SomeApp 0x0092b511 sigabrt_signal_handler + 112
2 libsystem_c.dylib 0x321817ed _sigtramp + 48
3 libsystem_c.dylib 0x3217720f pthread_kill + 54
4 libsystem_c.dylib 0x3217029f abort + 94
5 SomeApp 0x008ceccb monoeg_g_log + 122
6 SomeApp 0x008d386b get_numerous_trampoline + 134
7 SomeApp 0x008d3b33 mono_aot_get_imt_thunk + 34
8 SomeApp 0x00921be5 initialize_imt_slot + 72
9 SomeApp 0x0092294f build_imt_slots + 642
10 SomeApp 0x00922a29 mono_vtable_build_imt_slot + 80
11 SomeApp 0x008fd90d mono_convert_imt_slot_to_vtable_slot + 212
12 SomeApp 0x008fdab9 common_call_trampoline + 180
13 SomeApp 0x008fc78b mono_vcall_trampoline + 158
14 SomeApp 0x005ec748 generic_trampoline_vcall + 136
...
これらの各ビューは UINavigationController にプッシュされており、プレゼンターは 2 つのビューがスタックにプッシュされるまで、イベントをビューに問題なくアタッチできることに注意してください。
私の当初の想定では、GC が積極的にメモリを収集していましたが、インターフェイスを削除して具体的な型にイベントをアタッチしようとしました。
public SomePresenter(SomeView view)
{
_view = view;
_view.Loaded += Loaded;
_view.NextClicked += NextClicked;
_view.PreviousClicked += PreviousClicked;
_view.Unloaded += Unloaded;
}
すべて正常に動作します。不気味な
ここで何が起こっているのか知っている人がいたら、ぜひ聞いてみたいです!