迅速正确的方式来加载xib文件
在swift项目中加载xib文件有一些奇怪的问题。 这太令人沮丧了,因为我已经知道如何在Obj-C中做到这一点。 但是,因为迅捷是快速的,所以你不能像你这样做。:/
所以我创build了IconTextFiled.xib和IconTextField.swift。 (扩展UITextField)在xib中,我填写Idenity检查器中的字段类和故事板中,我做一些textFields相同。 所以我们只需要从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) }
但是,这没有用。 我不知道为什么,但它试图创造更多的对象和崩溃
最后我find了扩展
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
在Daniel anwser之后继续
我目前的代码
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) } }
这两个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
这适用于我:
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") } }
一旦loadNibNamed:owner:options:
被调用, view
和test
button按照预期连接到sockets。 添加笔尖的视图self的子视图层次结构使得笔尖的内容可见。
我更喜欢从nib加载,通过在协议扩展中实现loadFromNib()
函数,如下所示:
(这里解释: 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 } }
你可以使用这个:
if let customView = Bundle.main.loadNibNamed("MyCustomView", owner: self, options: nil)?.first as? MyCustomView { // Set your view here with instantiated customView }