Swift正确加载xib文件的方法

Bła*_*żej 14 interface-builder xib ios swift

我在swift项目中加载xib文件有一些奇怪的问题.这太令人沮丧,因为我已经知道如何在Obj-C中做到这一点.但是因为swift很快,所以你不能像你那样做..:/

所以我创建了IconTextFiled.xib和IconTextField.swift.(扩展UITextField)在xib中我在Idenity检查器中填充字段Class,在故事板中我对一些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;
}
Run Code Online (Sandbox Code Playgroud)

所以我想如果我翻译成swift就会很好.

required init(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    let nib:NSArray = NSBundle.mainBundle().loadNibNamed("IconTextField", owner: self, options: nil)
    self = nib.objectAtIndex(0)
}
Run Code Online (Sandbox Code Playgroud)

但那不起作用.我不知道为什么,但它试图创建更多的对象和崩溃

最后我发现了扩展

extension IconTextField {
    class func loadFromNibNamed(nibNamed: String, bundle : NSBundle? = nil) -> IconTextField? {
        return UINib(
            nibName: nibNamed,
            bundle: bundle
            ).instantiateWithOwner(nil, options: nil)[0] as? IconTextField
    }
}
Run Code Online (Sandbox Code Playgroud)

所以在ViewController中它看起来像

@IBOutlet var password: IconTextField!
override func viewDidLoad() {
    super.viewDidLoad()
    password = IconTextField.loadFromNibNamed("IconTextField")
}
Run Code Online (Sandbox Code Playgroud)

再次失败.你能告诉我你是如何加载和使用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)
    }   
}
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

这两个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;>
Run Code Online (Sandbox Code Playgroud)

它应该只有两个initWithCoder.它接口func loadNibNamed正在调用initWithCoder

Dan*_* T. 8

这对我有用:

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")
    }
}
Run Code Online (Sandbox Code Playgroud)

一旦loadNibNamed:owner:options:被调用view,test按钮就会按预期连接到插座.添加笔尖的视图self的子视图层次结构使得笔尖的内容可见.


Sam*_*Sam 6

我更喜欢从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
  }

}
Run Code Online (Sandbox Code Playgroud)