はじめに
こんにちは、@hiro128_777です。
iOSDC で 以下の通り Xamarin.iOS の仕組みについてお話させていただきました。
www.youtube.com
ですが、時間が足りなくて話しきれなかったことが多いので、blog でもう少し詳しく説明していこうと思います。
前回のお話はこちらです。
hiro128.hatenablog.jp
今回から、Xamarin.iOS がメモリーリークするメカニズムについての説明に入っていきます。
今回のお話に役に立つ iOS アプリのアーキテクチャーについてはこちらの公式ドキュメントも是非ご参照ください。
docs.microsoft.com
Xamarin.iOS で大変なのは、プラットフォーム固有の部分だけ
まず、最初に大事なことを確認しますと、Xamarin.iOS で、メモリリークやイベントの消失など「クセ」があり大変なのは、プラットフォーム固有の部分だけです。.NET の世界で閉じていることの多いロジック部分は、センサー類などの機種依存コードのDI部分を除けばとても安定しています。
そして、プラットフォーム固有の部分とは、具体的には以下の2つです。
NSObject を継承したクラス
public class SomeClass : NSObject { }
※ NSObject 自体も、 INativeObject を実装しています。
INativeObject を実装するクラス
public class SomeClass : ISomeInterface { } public interface ISomeInterface : INativeObject { }
この2つの共通点は、ネイティブオブジェクトつまり Objective-C の世界へのポインター(ハンドル)を持っていることです。ネイティブの世界へのハンドルを持っているため適切に扱わないとからリークします。
Windows の世界でも FileStream など、Win32 API の世界へのポインターを持つものを適切に扱わないとリークしてしまうのと同じことです。
INativeObject の定義
using System; namespace ObjCRuntime { // // 概要: // A simple interface that is used to expose the unmanaged object pointer in various // MonoTouch classes. // // コメント: // All this interface requires is for a class to expose an IntPtr that points to // the unmanaged pointer to the actual object. public interface INativeObject { // // 概要: // Handle (pointer) to the unmanaged object representation. // // コメント: // This IntPtr is a handle to the underlying unmanaged representation for this object. IntPtr Handle { get; } } }
ネイティブとマネージド
ネイティブとマネージドの定義は以下の通りとなります。
ネイティブ
- Objective-C ランタイムで実行されるコード
マネージド
- mono ランタイムで実行されるコード
そして、Xamarin.iOS(マネージド)の世界の裏には隠れた Objective-C(ネイティブ)の世界がある事を常に意識してください。この表と裏の世界との関係性によって、メモリーリークが発生します。
それでは、今回は以上となります。
次回はこちらです。
hiro128.hatenablog.jp