はじめに
こんにちは、@hiro128_777です。
iOSDC で 以下の通り Xamarin.iOS の仕組みについてお話させていただきました。
www.youtube.com
ですが、時間が足りなくて話しきれなかったことが多いので、blog でもう少し詳しく説明していこうと思います。
前回のお話はこちらです。
hiro128.hatenablog.jp
前回は、ネイティブとマネージドの話でした。そして、ネイティブオブジェクトにはさらに2種類のオブジェクトがあります。今回はその説明となります。
Wrapper type と User type
Xamarin.iOS で、取扱いに気をつけなくてはいけないのは、ネイティブオブジェクトですが、ネイティブオブジェクトにはさらに、Wrapper type と User type という2つの型があります。Xamarin.iOS における GC の挙動を考える上で、この2つの型の区別はとても重要になります。
Wrapper type
UIView や UIButton のような Objective-C の型をラップした型です。
メモリーリークはしません。
public override void ViewDidLoad() { base.ViewDidLoad(); var button = new UIButton(); }
Wrapper type の特徴
- マネージドの世界では、ネイティブオブジェクトのインスタンスへのハンドルだけのみを持ちます。(マネージドな世界だけで保持されているステートは持ちません)
- Wrapper type のインスタンスの寿命は、ネイティブオブジェクトの寿命とは無関係です。
- Wrapper type のインスタンスは、マネージドな世界にネイティブオブジェクトへのハンドル以外には何も保持していないので、GC の判断によっていつでも自由に解放できます。
- もし、後で再びそのオブジェクトが必要になった場合には Wrapper type のインスタンスが再度作成されるます。
- Wrapper type としてインスタンス生成されても、イベントのアタッチなどでマネージドな世界だけで管理されているステートを持ったタイミングで、User type にアップグレードされます。
User type
下記の MyButton のように、UIView や UIButton のような Wrapper type を継承し派生した型で Objective-C に対応する型が無いものです。
いつマネージ側の参照が解放され。ネイティブオブジェクトが破棄されるかがポイントです。(メモリーリークのリスクがあります)
public override void ViewDidLoad() { base.ViewDidLoad(); var button = new MyButton(); } public class MyButton : UIButton { public string Id { get; set; } }
User type の特徴
- マネージドの世界では、ネイティブオブジェクトのインスタンスへのハンドルの他に、マネージドな世界だけで管理されているステートを持ちます。
- User type のインスタンスの寿命は、ネイティブオブジェクトの寿命と関連があります。
- User type のインスタンスは マネージドな世界だけで管理されているステートを持つ可能性があるため GC の判断によって自由に解放することはできません。
- Xamarin.iOS はマネージオブジェクトを必要な間はずっと生かし続けることを保証ために GCHandle を作成し、回収されないようにします。
今回は以上となります。
次回はこちらです。
hiro128.hatenablog.jp