2012-03-26 2 views
4

ich verwendet habe dieses Tutorial mehrmals: http://www.alexyork.net/blog/2011/07/18/creating-custom-uitableviewcells-with-monotouch-the-correct-way/die Erstellung von benutzerdefinierten UITableCellView versteht - Laden von Nibs in Monotouch

Aber es gibt einen Code-Abschnitt darin, dass ich nicht gut verstehen:

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

Ich habe versucht, dies zu entfernen - um die LoadNib in den Konstruktoren zu platzieren - aber das ist falsch gegangen mit den Steckdosen nur nicht richtig verdrahtet.

Kann jemand etwas Licht auf das werfen, was hier vor sich geht? Warum kann ich diese Nib-Datei nicht einfach in den Konstruktoren laden? Warum müssen zwei Zelleninstanzen tatsächlich erstellt werden? Was passiert eigentlich im Hintergrund? Kann der Code verbessert werden?

interessieren, darüber zu lernen, wie ich es oft tue, und ich würde gerne den Prozess sauberer

Stuart

machen Wenn es hilft, ist ein Beispiel Zelle: https://github.com/slodge/MvvmCrossConference/blob/master/Cirrious.Conference.UI.Touch/Cells/SessionCell2.cs

+1

Ich habe versucht, eine vollständige Antwort zu schreiben, aber ich bin immer noch nicht in der Lage. Es gibt eine Menge Zeug darüber. Kurz gesagt: Sie brauchen keine Outlets von Ihrer Zelle, die mit dem Eigentümer Ihrer Datei in der NIB verbunden sind, und der Besitzer, den Sie an LoadNib (..) übergeben, sollte Outlets deklariert haben. Ich schreibe gerade einen Artikel über NIB-Laden, von dem ich glaube, dass er viel erklärt. Bis dahin überprüfen Sie das Beispielprojekt, das ich erstellt habe: http://github.com/dtavlikos/JTNibManager –

+0

Danke. Wir freuen uns auf den Blogbeitrag und auf das Lernen. Ich würde dir gerne den Sib-Editor mehr lieben, aber momentan finde ich den ganzen Prozess ein wenig verwirrend (und vielleicht auch fehlerhaft) – Stuart

+0

überprüfe meine Antwort. –

Antwort

5

des Werfen wir einen Blick bei den Dingen eins nach dem anderen.

Die LoadNib-Methode entcharchiert (und instanziiert) den Inhalt einer NIB. Der erste Parameter ist der Name der NIB und der zweite Parameter ist der Besitzer der NIB, die geladen wird. Das heißt, das Platzhalterobjekt "File's Owner" der NIB, das in diesem Fall vermutlich nur ein NSObject ist.

Die LoadNib-Methode gibt auch ein NSArray von Objekten zurück. Diese Objekte sind die Objekte der obersten Ebene der NIB, die in diesem Fall die benutzerdefinierte Zelle ist, die Sie in der NIB erstellt haben.

Ich nehme an, wenn Sie den obigen Code im Konstruktor bewegen, Sie so etwas wie dies umzusetzen:

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

Wenn Sie dies nicht tun, und Ihre Implementierung ist anders, aber Sie sind immer noch mit LoadNib im Konstruktor, die Verkaufsstellen werden weiterhin nicht beibehalten. Sie sind in Ordnung, aber sie werden nicht beibehalten. Es ist nicht der MonoTouch GC, der ansetzt oder irgendetwas, es ist der native Ausgang, der automatisch freigegeben wird. Sie fragen sich vielleicht "aber warum kann ich LoadNib im Konstruktor eines UIViewController verwenden und bekomme trotzdem meine Ausgänge?". Das ist richtig, Sie können die LoadNib im Konstruktor eines UIViewControllers verwenden, aber es gibt einen wichtigen Unterschied: UIViewController ist das Platzhalterobjekt Ihres Dateibesitzers. Wenn Sie versuchen, dasselbe mit einem Controller zu tun, der nicht der Eigentümer der Datei ist, erhalten Sie den gleichen Fehler beim Beibehalten der Ausgänge.

Was Sie grundsätzlich von der LoadNib-Methode benötigen, ist das Rückgabearray von Top-Level-Objekten. Also, um es im Konstruktor funktioniert, die „richtige“ Weg wäre:

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

das ist im Grunde das gleiche, was Sie außerhalb des Konstrukteurs des NIB laden tun. Aber natürlich können wir "das = etwas" nicht machen. Also, zusammenfassend mit der LoadNib-Erstellung: Ihre "MyCustomCell" ist ein Top-Level-Objekt und wird uns über den Rückgabewert der LoadNib zur Verfügung gestellt und nicht durch Übergabe als Eigentümer.

Das nächste, was Sie richtig bemerkt haben, ist über die beiden Instanzen: Ich glaube, das ist auch falsch.Werfen Sie einen Blick auf Ihren Code oben, mit einigen Kommentaren:

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? 

Ich denke, das ist ein Speicherleck. Beachten Sie die folgenden jedoch:

// 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 

Der Besitzer des NIB ist jetzt die Tabellenansicht. Die Tabellenansicht wird von der Laufzeit behandelt (in den meisten Fällen zumindest). eine Instanz zu erstellen, erstellen Sie einfach eine statische Methode

Wenn Sie noch in Ihrer MyCustomCell Klasse verwenden LoadNib wollen:

// 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; 
} 

Für weitere Informationen über NIB Laden:

Can you NIB it?

Apple's Resource Programming Guide on NIB files

Ich hoffe, das hilft.

+0

Dimitri, tolle Antwort, hatte gerade einen Kommentar. Ich bin mir nicht sicher, ob es sinnvoll ist, 'views = null' oder' topLevelObjects = null' zu setzen. Wenn es sich um lokale Variablen handelt, müssen Sie sie nicht auf null setzen - sie erhalten kein GC'ed. Ich liebe deine "Kannst du es NIB?" Artikel, habe mich selbst über die Interna dieses Materials gewundert. – jonathanpeppers

+0

Hallo Jonathan. Du hast recht, es ist nur, dass ich in letzter Zeit viel zu vielen ObjC-Sachen gelesen habe. Soweit NIB laden, bereite ich mehr Zeug vor, bleiben Sie dran ...;) –

+0

Ja, ich habe in C# so lange gearbeitet, ich nehme es als selbstverständlich an. Ich bin mir nicht sicher, ob ich es in der Obj-C-Welt schaffen würde. – jonathanpeppers

Verwandte Themen