2016-01-07 13 views
13

Ich habe versucht, @ IBDesignable UIView Unterklasse nach diesem Tutorial (link). Erste benutzerdefinierte Ansicht geht gut. Aber wenn ich versuche, einen anderen zu machen, habe ich Fehler. Zuerst bekam ich failed to update auto layout status: the agent crashed und Failed to render instance of .... Irgendwie fing ich an, in der Lage zu sein, ein Projekt mit diesen Fehlern zu biologisieren und auszuführen, aber dann erhalte ich einen neuen Fehler - EXC_BAD_ACCESS ... on line let view = nib.instantiateWithOwner(self, options: nil)[0] as! UIView. Hier ist die ganze Methode:Instantiate Ansicht von Nib wirft Fehler

func loadViewFromNib() -> UIView { 

     let bundle = NSBundle(forClass: self.dynamicType) 
     let nib = UINib(nibName: "advancedCellView", bundle: bundle) 
     let view = nib.instantiateWithOwner(self, options: nil)[0] as! UIView 

     return view 
    } 

Mit ersten benutzerdefinierten UIView ist kein Problem. Ich benutze denselben Code ..

enter image description here

Irgendwelche Ideen? Danke

+1

Sie schrieb: "Erste benutzerdefinierte Ansicht geht es gut." Bedeutet das, dass Sie die Ansicht tatsächlich einmal laden können, aber wenn Sie versuchen, sie erneut zu laden, erhalten Sie einen Fehler? –

+1

Was ist der Grund für die Verwendung von 'NSBundle: forClass:' anstatt nur auf 'NSBundle.mainBundle()' zuzugreifen? Ist diese "Feder" in einem anderen Bundle gespeichert? –

+1

Das deutet darauf hin, dass das Problem nicht mit dem Code, der die 'nib' lädt und instanziiert, sondern mit etwas in der' xib'-Datei selbst ist. Haben Sie die 'Klasse' für Ihre View-Unterklasse im Interface-Builder für die' xib' geändert? –

Antwort

29

Die loadViewFromNib()-Methode, die Sie veröffentlichen, sieht gut aus, Sie erhalten das Bundle korrekt und geben den Namen der Nib-Datei als Zeichenfolgenliteral an, sodass die Nib gefunden werden sollte. Wie jemand anderes bemerkt hat, stimmt wahrscheinlich etwas mit dem Einrichten der Feder nicht. Hier sind ein paar Dinge zu überprüfen:

  1. Sie sollten AdvancedCellView als benutzerdefinierte Benutzerklasse der Datei im Identity Inspector festgelegt haben.
  2. Überprüfen Sie, ob das Modul auch korrekt ist - normalerweise möchten Sie es nur leer lassen.
  3. Die benutzerdefinierte Klasse für die Ansicht sollte nicht festgelegt werden, lassen Sie es nur als Standard (UIView). Wenn Sie einen aussagekräftigeren Namen als "Ansicht" in der Seitenleiste haben, ist es wahrscheinlich falsch.
  4. Überprüfen Sie, dass Sie nur ein Top-Level-Objekt in der Spitze haben. Die Seitenleiste sollte ohne weitere Einträge wie folgt aussehen, wenn der Ansichtsbaum minimiert ist.

Nib hierarchy with only one top level view

N. B. Diese Antwort bezieht sich auf das Lernprogramm, mit dem das OP verknüpft ist, und nicht auf den einzig richtigen Weg zum Einrichten einer Schreibfeder.

+0

Da der OP-Code die Spitze manuell lädt und die 'view'-Eigenschaft direkt setzt, ist es nicht klar, ob es notwendig wäre, die Klasse des Eigentümers der Datei in der nib-Datei zu setzen. Es hat in keinem Fall Auswirkungen auf das Laufzeitverhalten, sondern nur auf die Möglichkeit, Verbindungen in Interface Builder herzustellen. Es ist jedoch falsch zu sagen, dass die Klasse der Ansicht nicht in der nib gesetzt werden sollte (wenn das OP tatsächlich möchte, dass es eine Unterklasse von "UIView" ist); Das würde * das Laufzeitverhalten beeinflussen, da diese Information vom Unarchivierer verwendet wird, um zu bestimmen, welche Klasse instanziiert werden soll. – jlehr

+0

Danke, das ist die richtige Antwort – Lachtan

+0

@jlehr wahr, es ist nicht immer der Fall, dass die Klasse nicht in der Spitze gesetzt werden sollte, aber das OP folgte einem Tutorial, das ihn die Ansicht von der Spitze in den 'init (Frame :) 'und' init (coder:) 'Methoden. In diesem Fall führt das Festlegen der benutzerdefinierten Klasse für die Ansicht zu einer Endlosschleife, wenn Sie die Spitze laden, es sei denn, Sie haben anderen Code, um dies zu verhindern. –

0

Versuchen Sie, dies stattdessen zu tun. Immer funktioniert für mich:

let picker = NSBundle.mainBundle().loadNibNamed("advancedCellView", owner: nil, options: nil) 
let view = picker[0] as! UIView 

return view 

Lassen Sie mich wissen, ob das funktioniert

+0

Danke für die Antwort. Es funktioniert nicht in der ersten benutzerdefinierten UIView. Überschreibt 'App beenden aufgrund der nicht abgefangenen Ausnahme 'NSUnknownKeyException', Grund: '[ setValue: forUndefinedKey:]: Diese Klasse ist für den Schlüssel captionLabel nicht schlüsselcodierfähig.'' – Lachtan

+0

Das ist ein anderes Problem. Sie müssen das Label im Storyboard mit Ihrer benutzerdefinierten Ansichtsklasse verbinden. – brl214

2

Die instantiateWithOwner(options:) Methode ein Array zurückgibt, nicht eine Ansicht, so eine Zwangs gesenkten zu UIView wird nie funktionieren. Versuchen Sie stattdessen, den tatsächlichen Typ [AnyObject] zu übergeben.

Die Elemente im Array entsprechen Objekten auf oberster Ebene in der NIB-Datei. Daher sollte die Ansicht, an der Sie interessiert sind, eines der Array-Elemente sein. Angesichts des Namens Ihrer NIB-Datei wird es höchstwahrscheinlich nur ein Top-Level-Objekt im Array geben - die Zelle, die Sie laden möchten. Stellen Sie sicher, dass sich in der NIB-Datei nur ein Objekt der obersten Ebene befindet und dass es tatsächlich eine Instanz einer Unterklasse von UIView ist.

Beachten Sie, dass Ihre Implementierung möglicherweise ineffizient ist. Wenn Sie mehr als eine Zelle laden, sollten Sie die Instanz UINib zwischenspeichern, anstatt jedes Mal eine neue Instanz zu erstellen. Beachten Sie, dass Framework-Klassen wie UITableViewController Methoden zum Registrieren von Nibs integriert haben, die sich automatisch um diese Details kümmern, sodass Sie dies möglicherweise nicht selbst tun müssen.

+1

Die Methode instanziateWithOwner (options :) gibt ein Array von Objekten der obersten Ebene zurück, die aus der Spitze entpackt wurden, wie Sie sagen. Wenn diese Objekte jedoch keinen benutzerdefinierten Klassensatz haben, handelt es sich um UIViews, und der Downcast funktioniert einwandfrei. Ich denke nicht, dass es ein erzwungener Downcast sein sollte, aber das ist ein anderes Thema. –

+0

Heh, du hast recht - sieht aus, als hätte ich das '[0]' dort verpasst. Ich werde meine Antwort aktualisieren. – jlehr

0

Ich schaute auf das Tutorial und entdeckte, dass Sie den Fehler erhalten, wenn Sie das View-Element in Ihrem benutzerdefinierten Xib ableiten. Stellen Sie sicher, dass Sie den "Eigentümer der Datei" nur für Ihre benutzerdefinierte Klasse festgelegt haben.

enter image description here