Быстрый способ загрузки xib файла
У меня есть странная проблема с загрузкой xib файла в проекте swift. Это так расстраивает, потому что я уже знаю, как это сделать в Obj-C. Но так как быстрый быстрый, так что вы не можете сделать это, как и вы..:/
Итак, я создал IconTextFiled.xib и IconTextField.swift. (расширяет UITextField) В xib я заполняю поле Class в инспекторе Idenity, а в раскадровке я делаю то же самое для некоторых текстовых полей. Итак, мы можем просто добавить загрузку из xib в метод init? Нет.
В objc я сделал бы это так:
- (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;
}
Итак, я подумал, что если перевести на быстрый, это будет хорошо.
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
let nib:NSArray = NSBundle.mainBundle().loadNibNamed("IconTextField", owner: self, options: nil)
self = nib.objectAtIndex(0)
}
Но это не работает. Я не знаю, почему, но он пытается создать гораздо больше объектов и сбоев
Наконец, я нашел расширение
extension IconTextField {
class func loadFromNibNamed(nibNamed: String, bundle : NSBundle? = nil) -> IconTextField? {
return UINib(
nibName: nibNamed,
bundle: bundle
).instantiateWithOwner(nil, options: nil)[0] as? IconTextField
}
}
Итак, в ViewController это выглядит как
@IBOutlet var password: IconTextField!
override func viewDidLoad() {
super.viewDidLoad()
password = IconTextField.loadFromNibNamed("IconTextField")
}
И снова терпит неудачу. Не могли бы вы рассказать, как вы загружаете и используете xib файлы?
UPDATE
Последовательный после Даниэля Андерсера
Мой текущий код
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)
}
}
![enter image description here]()
Эти два var связаны с этими представлениями
Выход Consoleo был намного больше и заканчивался 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;>
Это должно быть только два initWithCoder. Он швы, что func loadNibNamed вызывает initWithCoder
Ответы
Ответ 1
Это работает для меня:
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 supposed to be")
}
}
Как только loadNibNamed:owner:options:
называется, кнопки view
и test
подключаются к выходам, как ожидалось. Добавление иерархии подкадров в представлении nib позволяет видеть содержимое пива.
Ответ 2
Я предпочитаю загружать из nib, реализуя функцию loadFromNib()
в расширении протокола следующим образом:
(как описано здесь: fooobar.com/questions/76579/...)
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
}
}
Ответ 3
Вы можете использовать это:
if let customView = Bundle.main.loadNibNamed("MyCustomView", owner: self, options: nil)?.first as? MyCustomView {
// Set your view here with instantiated customView
}