2012-03-26 4 views
4
にニブからのロードを

私が使用したこのチュートリアルに数回:http://www.alexyork.net/blog/2011/07/18/creating-custom-uitableviewcells-with-monotouch-the-correct-way/カスタムUITableCellViewの作成を理解する - MonoTouchで

しかし、私は十分に理解していないということでコードのセクションがあります:

cell = new MyCustomCell(); 
    var views = NSBundle.MainBundle.LoadNib("MyCustomCell", cell, null); 
    cell = Runtime.GetNSObject(views.ValueAt(0)) as MyCustomCell; 
は、

私はこれを取り除こうとしました - コンストラクタの中にLoadNibを置くために - しかし、これは正しく接続されていないコンセントで間違っていました。

ここでは何が起こっているのか誰かが分かりますか?なぜ、このNibファイルをコンストラクタ内にロードできないのですか?なぜ2つのセルインスタンスを実際に作成する必要がありますか?バックグラウンドで実際に何が起こっていますか?コードを改善できますか?

私はかなり頻繁にそれを行うと私はプロセスをきれいにするのが大好きですと、これについて

スチュアート

を学ぶことに興味

それが助け場合は、例えば、細胞がある:https://github.com/slodge/MvvmCrossConference/blob/master/Cirrious.Conference.UI.Touch/Cells/SessionCell2.cs

+1

私は完全な答えを書こうとしましたが、私はまだできません。それについてはたくさんのことがあります。要するに:NIBのFile's Ownerに接続されているセルからのアウトレットと、LoadNib(..)に渡したアウトレットがアウトレットを宣言している必要があります。私は現在、多くのことを説明していると信じているNIBの読み込みに関する記事を書いています。それまでは、私が作成したサンプルプロジェクトを確認してください:http://github.com/dtavlikos/JTNibManager –

+0

ありがとうございました。ブログ投稿と学習を見下ろす。私はあなたにシブのエディタをもっと愛していますが、現在、私はプロセス全体がちょっと混乱していることを知っています(そしてたぶんバグもあります)。 – Stuart

+0

私の答えをチェックしてください。 –

答えて

5

はのは、見てみましょう一度に1つのもので。

LoadNibメソッドは、NIBの内容をアーカイブ解除(およびインスタンス化)します。最初のパラメータはNIBの名前で、2番目のパラメータはロードされるNIBの所有者です。つまり、NIBの "File's Owner"プレースホルダオブジェクトです。この場合、これは単なるNSObjectです。

LoadNibメソッドは、オブジェクトのNSArrayも返します。これらのオブジェクトはNIBのトップレベルオブジェクトです。この場合、NIBで作成したカスタムセルです。

は、私はあなたがコンストラクタで上記のコードを移動するとき、あなたはこのような何かを実装するとします。

public MyCustomCell() : base() 
{ 
    NSBundle.MainBundle.LoadNib("MyCustomCell", this, null); 
} 

そうしないと、あなたの実装が異なっているが、あなたはまだコンストラクタでLoadNibを使用している場合は、アウトレットは依然として保持されません。彼らは大丈夫ですが、それらは保持されません。 MonoTouch GC以外のものではなく、オートリリースされているネイティブのアウトレットです。 「なぜUIViewControllerのコンストラクタでLoadNibを使用しても、私のアウトレットを取得できますか?」という疑問があります。それは正しいです、あなたは、UIViewControllerのコンストラクタでLoadNibを使用することができますが、1つの重要な違いがあります:そのUIViewControllerはあなたのファイルの所有者プレースホルダーオブジェクトです。 File's Ownerではないコントローラーで同じことをしようとすると、アウトレットを保持するのと同じ失敗が起こります。

LoadNibメソッドから基本的に必要なものは、トップレベルオブジェクトの戻り値の配列です。だから、それはコンストラクタで動作させるために、「正しい」方法は次のようになります。基本的には、コンストラクタの外NIBをロードするためにやっているのと同じことです

public MyCustomCell() : base() 
    { 
     NSArray arr = NSBundle.LoadNib("MyCustomCell", this, null); 
     this = Runtime.GetNSObject(arr.ValueAt(0)); // should retain everything, 
     //BUT: Compile error! 
    } 

。しかしもちろん、私たちは「これ=何か」をすることはできません。したがって、LoadNibの作成を要約すると、「MyCustomCell」はトップレベルのオブジェクトであり、LoadNibの戻り値を介して提供され、所有者として渡されることはありません。

あなたが正しく気付いたのは、2つのインスタンスについてです。私はそれも間違っていると信じています。上のコードを見て、いくつかのコメントを付けてください:

cell = new MyCustomCell(); // Created a new instance of MyCustomCell 
var views = NSBundle.MainBundle.LoadNib("MyCustomCell", cell, null); // Assigned it as an owner 
cell = Runtime.GetNSObject(views.ValueAt(0)) as MyCustomCell; // What happens to the owner? 

私はそれがメモリリークだと思います。ただし、次の点を考慮してください。

// Not needed 
//cell = new MyCustomCell(); 
var views = NSBundle.MainBundle.LoadNib("MyCustomCell", tableView, null); // Owner is now the tableView 
cell = Runtime.GetNSObject(views.ValueAt(0)) as MyCustomCell; 
views = null; // Don't need it anymore 

NIBの所有者がテーブルビューになりました。テーブルビューはランタイムによって処理されます(ほとんどの場合、少なくとも)。

Can you NIB it?

Apple's Resource Programming Guide on NIB files:NIBのロードの詳細情報については

// Inside MyCustomCell 
public static MyCustomCell CreateCell(NSObject owner) 
{ 
    NSArray topLevelObjects = NSBundle.MainBundle.LoadNib("MyCustomCell", owner, null); 
    MyCustomCell customCell = Runtime.GetNSObject(topLevelObjects.ValueAt(0)) as MyCustomCell; 
    topLevelObjects = null; 
    return customCell; 
} 

:あなたはまだインスタンスを作成するためにあなたのMyCustomCellクラス内LoadNibを使用したい場合は

、単に静的メソッドを作成

こちらがお役に立てば幸いです。

+0

Dimitri、素晴らしい答え、ちょうどコメントがありました。 'views = null'や' topLevelObjects = null'を設定しても何の助けにもなりません。ローカル変数であれば、nullに設定する必要はありません.GC'edになりますが問題ありません。私はあなたのことを愛していますか?記事は、自分自身の内部のことを疑問に思っていた。 – jonathanpeppers

+0

こんにちはジョナサン。あなたは正しいです、それは私が多くのObjCのものに最近読んできたことです。 NIBのローディングまで、私はより多くのものを準備しています...;) –

+0

ええ、私はC#で長年働いてきました。私はObj-Cの世界でそれを作ろうとは思っていません。 – jonathanpeppers

関連する問題