Benutzerdefinierte UIView-Unterklasse, mit XIB in Swift
Bin ich mit Swift und Xcode 6.4 für was es Wert ist.
Also ich habe einen view-controller wird mit mehrere Paare von UILabels und UIImageViews. Ich wollte das UILabel-UIImageView-pair-Mädchen in eine eigene UIView, so konnte ich einfach die Wiederverwendung der gleichen Struktur wiederholt innerhalb der oben genannten view-controller. (Ich bin mir bewusst, könnte dies übersetzt werden in eine UITableView, aber für den sake von ~lernen~ bitte Geduld mit mir). Diese entpuppt sich als eine mehr komplizierte Prozess, als ich es mir vorgestellt hatte, ich habe Schwierigkeiten, herauszufinden, den "richtigen" Weg, um diese arbeiten alle in IB.
Derzeit habe ich schon zappelte, um mit einer UIView-Unterklasse und zugehörige XIB und überschreiben Sie die init(frame:) und init(coder), laden der view aus der nib und das hinzufügen von es als eine Untersicht. Dies ist, was ich gesehen/Lesen rund um das internet so weit. (Dies ist ungefähr: http://iphonedev.tv/blog/2014/12/15/create-an-ibdesignable-uiview-subclass-with-code-from-an-xib-file-in-xcode-6).
Dieser hat mir das problem verursacht eine Endlosschleife zwischen init(Programmierer) und laden Sie die Feder aus dem bundle. Seltsamerweise ist keiner von diesen Artikeln oder den vorherigen Antworten auf stack overflow erwähne dies!
Ok also habe ich ein check-in init(coder), um zu sehen, wenn die Untersicht wurde bereits Hinzugefügt. Das "gelöst", die, scheinbar. Allerdings rannte ich in ein Problem mit meiner benutzerdefinierten Ansicht outlets wird null durch die Zeit, die ich versuchen, Ihnen einen Wert zuteilen.
Machte ich einen didSet und fügte hinzu, einen Haltepunkt, einen Blick zu nehmen...Sie sind definitiv festgelegt wird, zu einem Punkt, aber durch die Zeit, die ich versuchen, zu sagen, ändern Sie die Textfarbe eines Labels, das label ist gleich null.
Ich bin irgendwie reißen mir die Haare aus hier.
Wiederverwendbare Komponenten scheinen, wie software-design 101, aber ich fühle mich wie Apple verschworen gegen mich. Sollte ich suchen, um container VCs hier? Sollte ich einfach verschachteln von views und ein blöd riesige Menge von Verkaufsstellen, die in meinem Haupt-VC? Warum ist das so gebogen? Warum muss jeder die Beispiele bei mir NICHT funktioniert?
Gewünschte Ergebnis vorgeben, die ganze Sache ist die VC, die Boxen sind die benutzerdefinierten uiviews ich will):
Vielen Dank für das Lesen.
Folgende ist meine eigene UIView-Unterklasse. In meinem Haupt-storyboard, ich habe UIViews mit der Unterklasse gesetzt, als Ihre Klasse.
class StageCardView: UIView {
@IBOutlet weak private var stageLabel: UILabel! {
didSet {
NSLog("I will murder you %@", stageLabel)
}
}
@IBOutlet weak private var stageImage: UIImageView!
var stageName : String? {
didSet {
self.stageLabel.text = stageName
}
}
var imageName : String? {
didSet {
self.stageImage.image = UIImage(named: imageName!)
}
}
var textColor : UIColor? {
didSet {
self.stageLabel.textColor = textColor
}
}
var splatColor : UIColor? {
didSet {
let splatImage = UIImage(named: "backsplat")?.tintedImageWithColor(splatColor!)
self.backgroundColor = UIColor(patternImage: splatImage!)
}
}
//MARK: init
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
if self.subviews.count == 0 {
setup()
}
}
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
func setup() {
if let view = NSBundle.mainBundle().loadNibNamed("StageCardView", owner: self, options: nil).first as? StageCardView {
view.frame = bounds
view.autoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight
addSubview(view)
}
}
/*
//Only override drawRect: if you perform custom drawing.
//An empty implementation adversely affects performance during animation.
override func drawRect(rect: CGRect) {
//Drawing code
}
*/
}
EDIT: Hier ist, was ich in der Lage gewesen, um so weit...
XIB:
Ergebnis:
Problem: Beim ersten Zugriff auf die label-oder image-outlets, Sie sind null. Bei der überprüfung am Haltepunkt der sagte, der Zugriff auf die Etiketten-und Bild-Untersichten sind da und die view-Hierarchie ist, wie erwartet.
Ich bin OK mit dabei, alle im code, wenn es das ist, was es braucht, aber ich bin nicht riesig, das zu tun, Autolayout-in-code, so würde ich das eher nicht wenn es einen Weg gibt, es zu vermeiden!
BEARBEITEN/FRAGE SHIFT:
Ich herausgefunden, wie man die Steckdosen aufhören, null.
Inspiration von diesem SO beantworten: Geladen Feder, aber die Aussicht Steckdose war nicht gesetzt - neu InterfaceBuilder außer anstelle von zuweisen der Ansicht, Steckdose, wies ich die einzelnen Komponente outlets.
Das war jetzt an dem Punkt, wo ich nur war, schleuderte scheisse an eine Wand und sehen, wenn es würde stick. Weiß jemand, warum ich dies tun musste? Welche Art von dunkler Magie ist das?
- haben Sie keine Lösung gefunden?
Du musst angemeldet sein, um einen Kommentar abzugeben.
War ich in der Lage zu arbeiten es um, aber die Lösung ist etwas tricky. Es ist zu diskutieren, ob der gain-Wert ist ein Aufwand, aber hier ist, wie ich es umgesetzt, rein in interface builder
Zuerst habe ich definiert eine benutzerdefinierte
UIView
Unterklasse namensP2View
Dies ist, wie es aussieht im interface builder
Dies ist, wie ich eingebettete diese benutzerdefinierte Ansicht im Beispiel-view-controller definiert, der auf ein storyboard. Eigenschaften von
P2View
sind, setzen Sie im attributes inspector.Gibt es 3 Punkte erwähnenswert
Erste:
Verwenden Sie die
Bundle(for: type(of: self))
beim laden der nib. Dies ist, weil der interface builder stellt die designables in der separaten Prozess, der die Haupt-bundle ist nicht das gleiche wie dein main bundle.Zweite:
Werden, wenn die Kombination
IBInspectables
mitIBOutlets
Sie haben sich daran zu erinnern, dass diedidSet
Funktionen aufgerufen werden, bevorawakeFromNib
Methode. Weil dieses, die Ausgänge sind nicht initialisiert, und Ihre app wird wahrscheinlich zu einem Absturz an dieser Stelle. Leider kann man nicht weglassen, diedidSet
- Funktion, da der interface builder nicht machen Ihre benutzerdefinierte Ansicht ein, so haben wir lassen diese schmutzig, wenn hier.Dritte:
Müssen wir irgendwie initialisieren unseren Kontrollen. Wir waren nicht in der Lage, es zu tun, wenn
didSet
- Funktion aufgerufen wurde, so haben wir die Verwendung der gespeicherte Wert in derIBInspectable
Eigenschaften und initialisieren Sie diese am Ende derawakeFromNib
Methode.Dies ist, wie können Sie implementieren eine benutzerdefinierte Ansicht auf eine Xib -, Betten Sie ihn in ein storyboard, konfigurieren es auf einem storyboard, habe es gerendert und sind mit einem nicht-Absturz-app. Es erfordert ein hack, aber es ist möglich.
Allgemeine Beratung über anzeigen re-use -
Du hast Recht, wiederverwendbar und composable Elemente-software 101. Interface Builder ist nicht sehr gut.
Speziell, xibs und Storyboards sind große Möglichkeiten, um Sie auf Ansichten definieren durch die Wiederverwendung von definierten Ansichten im code. Aber Sie sind nicht sehr gut für das definieren von Ansichten, die Sie sich wünschen, re-use innerhalb xibs und storyboards. (Es kann getan werden, aber es ist eine übung für fortgeschrittene.)
So, hier ist eine Faustregel. Wenn Sie bei der Definition einer Ansicht, die Sie wollen, um die Wiederverwendung von code, dann definieren Sie es wie Sie wollen. Aber wenn Sie bei der Definition einer Ansicht, die Sie wollen in der Lage sein, wieder zu verwenden, möglicherweise aus einem storyboard, dann definieren Sie diese Ansicht im code.
So, in Ihrem Fall, wenn Sie versuchen, eine benutzerdefinierte Ansicht, die Sie wollen, wieder verwenden von ein storyboard, würde ich es im code. Wenn Sie tot-set auf die Definition Ihrer Ansicht über einen xib, dann würd ich das definieren einer Ansicht im code und in seinem Initialisierer haben Sie initialisieren Ihre xib-definierte anzeigen und konfigurieren, der als Untersicht.
Beratung in diesem Fall
Hier ist in etwa, wie würden Sie definieren Ihre Ansicht in code:
Nun können Sie instanziieren Sie diese im code und oder über ein storyboard, obwohl Sie nicht bekommen eine live-Vorschau im Interface Builder so wie es ist.
Alternativ, hier ist in etwa, wie Sie definieren können, eine wiederverwendbare view basiert grundsätzlich auf eine xib, durch die Einbettung der xib-definierte Ansicht in die code-Ansicht definiert:
Nun können Sie den code-definierten Ansicht von storyboards oder von code, und es wird laden Sie Ihre nib-definiert Untersicht (und es gibt immer noch keine live-Vorschau bei der IB).