Ich habe ein seltsames Problem beim Laden der Xib-Datei in einem Swift-Projekt. Es ist so frustrierend, weil ich bereits weiß, wie es in Obj-C geht. Aber da Swift Swift ist, kannst du es nicht so machen wie du ..: /
Ich habe also IconTextFiled.xib und IconTextField.Swift erstellt. (erweitert UITextField) In xib fülle ich das Feld Class im Idenity-Inspector und im Storyboard mache ich dasselbe für einige TextFields. Also ist es gut zu gehen, nur das Laden von xib zur init-Methode hinzuzufügen? Nein.
In objc würde ich es so machen
- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
if (self) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"IconTextField" owner:self options:nil];
self = [nib objectAtIndex:0];
}
return self;
}
Also dachte ich, wenn ich zu Swift übersetze, wird es gut sein.
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
let nib:NSArray = NSBundle.mainBundle().loadNibNamed("IconTextField", owner: self, options: nil)
self = nib.objectAtIndex(0)
}
Aber das geht nicht. Ich weiß nicht warum, aber es wird versucht, viel mehr Objekte und Abstürze zu erstellen
Endlich fand ich eine Erweiterung
extension IconTextField {
class func loadFromNibNamed(nibNamed: String, bundle : NSBundle? = nil) -> IconTextField? {
return UINib(
nibName: nibNamed,
bundle: bundle
).instantiateWithOwner(nil, options: nil)[0] as? IconTextField
}
}
In ViewController sieht es also so aus
@IBOutlet var password: IconTextField!
override func viewDidLoad() {
super.viewDidLoad()
password = IconTextField.loadFromNibNamed("IconTextField")
}
Und wieder scheitern. Können Sie mir sagen, wie Sie Xib-Dateien laden und verwenden?
Ok folgt nach Daniel Anwser
Mein aktueller Code
class IconTextField: UITextField {
@IBOutlet var icon: UIImageView!
@IBOutlet weak var view: UIView!
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
NSLog("initWithCoder \(self)")
NSBundle.mainBundle().loadNibNamed("IconTextField", owner: self, options: nil)
self.addSubview(view)
}
}
Diese beiden Var sind mit diesen Ansichten verbunden
Consoleo-Ausgabe war viel größer und endete mit EXC_BAD_ACCESS
2014-10-24 10:09:09.984 testproject[20337:3757479] initWithCoder <stensgroup.IconTextField: 0x7be7bfb0;>
2014-10-24 10:09:09.984 testproject[20337:3757479] initWithCoder <stensgroup.IconTextField: 0x7be7ddf0;>
2014-10-24 10:09:09.985 testproject[20337:3757479] initWithCoder <stensgroup.IconTextField: 0x7be7fa20;>
2014-10-24 10:09:09.985 testproject[20337:3757479] initWithCoder <stensgroup.IconTextField: 0x7be814f0;>
2014-10-24 10:09:09.986 testproject[20337:3757479] initWithCoder <stensgroup.IconTextField: 0x7be830c0;>
2014-10-24 10:09:10.083 testproject[20337:3757479] initWithCoder <stensgroup.IconTextField: 0x7d183270;>
2014-10-24 10:09:10.084 testproject[20337:3757479] initWithCoder <stensgroup.IconTextField: 0x7d187cd0;>
2014-10-24 10:09:10.084 testproject[20337:3757479] initWithCoder <stensgroup.IconTextField: 0x7d189960;>
Es sollten nur zwei initWithCoder sein. Es scheint, dass func loadNibNamed initWithCoder
aufruft.
Das funktioniert für mich:
class IconTextField: UITextField {
@IBOutlet weak var view: UIView!
@IBOutlet weak var test: UIButton!
required init(coder: NSCoder) {
super.init(coder: coder)
NSBundle.mainBundle().loadNibNamed("IconTextField", owner: self, options: nil)
self.addSubview(view)
assert(test != nil, "the button is conected just like it's supposed to be")
}
}
Sobald loadNibNamed:owner:options:
aufgerufen wird, sind die view
- und test
-Tasten wie erwartet mit den Ausgängen verbunden. Durch Hinzufügen der Untersicht-Hierarchie des Ansichtselibs der Spitze wird der Inhalt der Spitze sichtbar.
Ich bevorzuge das Laden von der Spitze, indem ich die Funktion loadFromNib()
in einer Protokollerweiterung wie folgt implementiere:
(wie hier erklärt: https://stackoverflow.com/a/33424509/845027 )
import UIKit
protocol UIViewLoading {}
extension UIView : UIViewLoading {}
extension UIViewLoading where Self : UIView {
// note that this method returns an instance of type `Self`, rather than UIView
static func loadFromNib() -> Self {
let nibName = "\(self)".characters.split{$0 == "."}.map(String.init).last!
let nib = UINib(nibName: nibName, bundle: nil)
return nib.instantiateWithOwner(self, options: nil).first as! Self
}
}
Sie können dies verwenden:
if let customView = Bundle.main.loadNibNamed("MyCustomView", owner: self, options: nil)?.first as? MyCustomView {
// Set your view here with instantiated customView
}