5

私が理解しているように、MonoTouch で Cocoa オブジェクトを扱うときは、Cocoa オブジェクトへの参照を保持する必要があります。この理由は、ObjC ランタイムがまだオブジェクトへの参照を保持している可能性があり、オブジェクトに "MonoTouch 参照" がない場合、オブジェクトがガベージ コレクションされる可能性があり、その結果、ObjC ランタイムがオブジェクトにEXC_BAD_ACCESSアクセスしようとするとすぐにエラーが発生する可能性があるためです。

たとえば、VC1 と VC2 という 2 つの UIViewController サブクラスがあるとします。ユーザーが VC1 のボタンをクリックすると、UI は VC2 に移動し、ユーザーは前後に移動できます。ユーザーが移動するたびに VC2 の新しいインスタンスを作成すると、古いインスタンスへの参照が失われるため、ガベージ コレクションがdidReceiveMemoryWarning行われ、次に UIViewController に伝達されたときにアプリがクラッシュします。

毎回同じインスタンスの VC2 を使用する必要がないように、古い参照を解放するにはどうすればよいですか? Dispose足りないようでした。

4

2 に答える 2

6

私が理解しているように、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
  • ネイティブネイティブXUIViewControllerへの参照を追加します(ネイティブ参照カウント == 2)。
  • アプリケーションは問題なく実行されます...
  • インスタンスへの参照を停止しMT.Xます (たとえば、変数をnullまたは別のインスタンスに設定します)。
  • もう参照がMT.Xないため、ガベージ コレクターはマネージドインスタンスを破棄し、これを呼び出しDisposeネイティブXへの参照を減らします (ネイティブ参照カウント == 1)。ただし、ビュー コントローラーによってまだ参照されている (0 ではない) ため、ネイティブインスタンスは解放されません。
  • UIViewController、ネイティブにトリガーする何かを行いますX.ViewWillUnload(たとえば、新しい をロードしようとしますUIView)。
  • まだネイティブに存在するためX(参照カウント == 1) 、管理対象ViewWillUnloadインスタンスに戻ろうとするそれを呼び出します...それは破棄されました。

この問題の解決策は、ネイティブ部分がジョブを完了するまでマネージドインスタンスを破棄しないようにすることです。

于 2012-07-23T13:01:43.833 に答える
1

私のアプリでも同じ状況があり、GC はオブジェクトを正しく収集します。言い換えれば、VC への参照を単純に無効にして、あとは GC に任せるだけの問題を経験したことはありません。

Disposeただし、メソッドを呼び出すと問題が発生しました。これを手動で行うべきではないようです。代わりに、GC がオブジェクトを収集してそのリソースを解放するのを待つ必要があります。基本NSObjectクラスのDisposeファイナライザーには への呼び出しがあるため、オブジェクトが収集されると、すべてのアンマネージ リソースが解放されます。

GC.Collectルート VC のDidReceiveMemoryWarningメソッドの一部でfor を呼び出すこともできます。

于 2012-07-23T12:34:53.963 に答える