私が理解しているように、MonoTouch で Cocoa オブジェクトを扱うときは、Cocoa オブジェクトへの参照を保持する必要があります。
そうではありません。MonoTouchマネージドインスタンスは、ネイティブインスタンスへの参照を保持します。マネージドインスタンスが存在する限り、ネイティブインスタンスは有効です (これらは参照カウントされ、MonoTouch はその参照を解放しないため)。
ネイティブ部分が必要である限り、MonoTouchマネージドインスタンスへの参照を保持する必要があります。
この理由は、ObjC ランタイムがオブジェクトへの参照を保持している可能性があるためです...オブジェクトはガベージ コレクションされる可能性があります。
ネイティブ (Objective C) インスタンスは、ガベージ コレクションではなく参照カウントされます。ネイティブ インスタンスは、参照カウントが 0 になるまで解放されません (関連付けられたマネージドインスタンスが存在する間は解放されません)。
また、ネイティブ インスタンスは、他のネイティブ インスタンスへの参照を保持できます。すべてのネイティブインスタンスに対応するマネージドインスタンスがあるわけではありません。
これにより、ObjC ランタイムがそれらにアクセスしようとするとすぐに EXC_BAD_ACCESS が発生します。
少なくともこの方法では、それは起こりません。OTOH あなたのケースで何が起こっているのかを伝えるのは難しいです (コードやクラッシュを見ずに)。
マネージドインスタンスがジョブを完了する前に(手動かどうかに関係なく) 破棄していると思われます。起こりうることを簡単に説明すると、次のようになります。
- 管理されたMT.X インスタンス (例: )を作成します
UIView
。
- これにより、ネイティブX が作成されて参照されます (ネイティブ参照カウント == 1)。
- イベントをオーバーライドする (またはデリゲートを追加する...) MT.X (ネイティブにも存在する) の `ViewWillUnload';
- MT.X インスタンスを別の (マネージド) インスタンスに割り当てます
UIViewController
。
- ネイティブ はネイティブX
UIViewController
への参照を追加します(ネイティブ参照カウント == 2)。
- アプリケーションは問題なく実行されます...
- インスタンスへの参照を停止し
MT.X
ます (たとえば、変数をnull
または別のインスタンスに設定します)。
- もう参照が
MT.X
ないため、ガベージ コレクターはマネージドインスタンスを破棄し、これを呼び出しDispose
てネイティブXへの参照を減らします (ネイティブ参照カウント == 1)。ただし、ビュー コントローラーによってまだ参照されている (0 ではない) ため、ネイティブインスタンスは解放されません。
- は
UIViewController
、ネイティブにトリガーする何かを行いますX.ViewWillUnload
(たとえば、新しい をロードしようとしますUIView
)。
- まだネイティブに存在するため
X
(参照カウント == 1) 、管理対象ViewWillUnload
インスタンスに戻ろうとするそれを呼び出します...それは破棄されました。
この問題の解決策は、ネイティブ部分がジョブを完了するまでマネージドインスタンスを破棄しないようにすることです。