Ich möchte eine Unterklasse erstellen UIView
und eine loginähnliche Ansicht anzeigen. Ich habe dies in Objective-C erstellt, möchte es aber jetzt auf Swift portieren. Ich verwende keine Storyboards, daher erstelle ich meine gesamte Benutzeroberfläche im Code.
Aber das erste Problem ist, dass ich implementieren muss initWithCoder
. Ich habe ihm eine Standardimplementierung gegeben, da er nicht aufgerufen wird. Wenn ich jetzt das Programm starte, stürzt es ab, weil ich es ebenfalls implementieren muss initWithFrame
. Jetzt habe ich folgendes:
override init() {
super.init()
println("Default init")
}
override init(frame: CGRect) {
super.init(frame: frame)
println("Frame init")
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
println("Coder init")
}
Meine Frage ist, wo ich mein Textfeld usw. erstellen soll. Und wenn ich nie Frame und Codierer implementiere, wie kann ich dies "verbergen"?
CGRectZero
glaube ich, wird empfohlen, zu verwendenCGRect.zeroRect
.Das ist einfacher.
quelle
Beispiel für eine benutzerdefinierte UIView-Unterklasse
Normalerweise erstelle ich iOS-Apps ohne Storyboards oder Schreibfedern. Ich werde einige Techniken teilen, die ich gelernt habe, um Ihre Fragen zu beantworten.
Unerwünschte
init
Methoden ausblendenMein erster Vorschlag ist, eine Basis
UIView
zu deklarieren , um unerwünschte Initialisierer auszublenden. Ich habe diesen Ansatz in meiner Antwort auf "Ausblenden von Storyboard- und Nib-spezifischen Initialisierern in UI-Unterklassen" ausführlich erörtert . Hinweis: Bei diesem Ansatz wird davon ausgegangen, dass SieBaseView
oder seine Nachkommen nicht in Storyboards oder Schreibfedern verwenden, da die App absichtlich abstürzt.Ihre benutzerdefinierte UIView-Unterklasse sollte von erben
BaseView
. Es muss super.init () in seinem Initialisierer aufrufen. Es muss nicht implementiert werdeninit(coder:)
. Dies wird im folgenden Beispiel gezeigt.Hinzufügen eines UITextField
Ich erstelle gespeicherte Eigenschaften für Unteransichten, auf die außerhalb der
init
Methode verwiesen wird. Ich würde dies normalerweise für ein UITextField tun. Ich bevorzuge es, Unteransichten innerhalb der Deklaration der Unteransichtseigenschaft wie folgt zu instanziieren :let textField = UITextField()
.Das UITextField ist nur sichtbar, wenn Sie es durch Aufrufen zur Unteransichtsliste der benutzerdefinierten Ansicht hinzufügen
addSubview(_:)
. Dies wird im folgenden Beispiel gezeigt.Programmatisches Layout ohne automatisches Layout
Das UITextField ist nur sichtbar, wenn Sie seine Größe und Position festlegen. Ich mache oft Layout in Code (ohne Auto Layout) innerhalb der layoutSubviews Methode .
layoutSubviews()
wird anfänglich aufgerufen und immer dann, wenn ein Größenänderungsereignis auftritt. Dies ermöglicht das Anpassen des Layouts abhängig von der Größe von CustomView. Wenn CustomView beispielsweise auf verschiedenen Größen von iPhones und iPads in voller Breite angezeigt wird und sich an die Drehung anpasst, muss es viele Anfangsgrößen berücksichtigen und die Größe dynamisch ändern.Sie können auf
frame.height
undframe.width
innerhalb verweisen,layoutSubviews()
um die Abmessungen von CustomView als Referenz zu erhalten. Dies wird im folgenden Beispiel gezeigt.Beispiel UIView-Unterklasse
Eine benutzerdefinierte UIView-Unterklasse, die ein UITextField enthält, das nicht implementiert werden muss
init?(coder:)
.Programmatisches Layout mit automatischem Layout
Sie können das Layout auch mithilfe des automatischen Layouts im Code implementieren. Da ich das nicht oft mache, werde ich kein Beispiel zeigen. Beispiele für die Implementierung des automatischen Layouts im Code finden Sie im Stapelüberlauf und an anderer Stelle im Internet.
Programmatische Layout-Frameworks
Es gibt Open Source-Frameworks, die das Layout in Code implementieren. Eine, die mich interessiert, aber noch nicht ausprobiert hat, ist LayoutKit . Es wurde vom Entwicklungsteam ein LinkedIn geschrieben. Aus dem Github-Repository: "LinkedIn hat LayoutKit erstellt, weil wir festgestellt haben, dass das automatische Layout für komplizierte Ansichtshierarchien in scrollbaren Ansichten nicht leistungsfähig genug ist."
Warum setzen
fatalError
ininit(coder:)
Wenn Sie UIView-Unterklassen erstellen, die niemals in einem Storyboard oder einer Schreibfeder verwendet werden, können Sie Initialisierer mit unterschiedlichen Parametern und Initialisierungsanforderungen einführen, die von der
init(coder:)
Methode nicht aufgerufen werden konnten . Wenn Sie init (coder :) nicht mit a versagt habenfatalError
, kann dies zu sehr verwirrenden Problemen führen, wenn Sie versehentlich in einem Storyboard / einer Feder verwendet werden. Der fatalError bestätigt diese Absichten.Wenn Sie beim Erstellen der Unterklasse Code ausführen möchten, unabhängig davon, ob dieser im Code oder in einem Storyboard / einer Feder erstellt wurde, können Sie Folgendes tun (basierend auf der Antwort von Jeff Gu Kang ).
quelle
fatalError
Indem Sie hinzufügen , verbieten Sie, diese Ansicht mit XIB-Dateien zu initiierenfatalError
Wenn Sie das nächste Mal in die Dealloc-Methode schreiben und uns mitteilen, dass dies nicht funktioniert, sollte diese Klasse ein Singleton sein. Wenn Sie es vorziehen, UI-Elemente im Code zu erstellen, sollten Sie alle anderen Möglichkeiten nicht manuell verbieten. Schließlich stellt sich die Frage, wie "programmgesteuert ohne Storyboards" erstellt werden kann, Xibs / Nibs werden jedoch nicht erwähnt. In meinem Fall muss ich mit programmgesteuert + xib ein Array von Zellen erstellen und diese übergeben.DropDownMenuKit
Dies funktioniert nicht, da der Autor dieser Bibliothek auch xibs verbietet.Es ist wichtig, dass Ihr UIView vom Interface Builder / Storyboard oder aus Code erstellt werden kann. Ich finde es nützlich, eine
setup
Methode zu haben, um das Duplizieren von Setup-Code zu reduzieren. z.Bquelle
Swift 4.0, Wenn Sie die Ansicht aus der XIB-Datei verwenden möchten, ist dies das Richtige für Sie. Ich habe die CustomCalloutView-Klasse Subklasse von UIView erstellt. Ich habe eine xib-Datei erstellt und in IB einfach den Dateieigentümer ausgewählt, dann den Attributinspektor ausgewählt, den Klassennamen auf CustomCalloutView gesetzt und dann den Ausgang in Ihrer Klasse erstellt.
// Jetzt füge es hinzu
quelle
Hier ist ein Beispiel, wie ich normalerweise meine Unterklassen (UIView) erstelle. Ich habe den Inhalt als Variablen, damit auf sie zugegriffen und sie möglicherweise später in einer anderen Klasse optimiert werden können. Ich habe auch gezeigt, wie ich das automatische Layout verwende und Inhalte hinzufüge.
Zum Beispiel habe ich in einem ViewController diese Ansicht in ViewDidLoad () initialisiert, da diese nur einmal aufgerufen wird, wenn die Ansicht sichtbar ist. Dann benutze ich diese Funktionen, die ich hier
addContentToView()
und dann macheactivateConstraints()
, um den Inhalt zu erstellen und Einschränkungen festzulegen. Wenn ich später in einem ViewController möchte, dass die Farbe einer Schaltfläche rot ist, mache ich das einfach in dieser speziellen Funktion in diesem ViewController. Etwas wie:func tweaksome(){ self.customView.someButton.color = UIColor.red}
quelle