Подтвердить что ты не робот

Быстрый способ загрузки 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

4b9b3361

Ответ 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
}