使用swib中的Nib自定义UIView,而不在视图控制器中使用loadFromNib

时间:2015-01-23 08:24:56

标签: ios swift uiview nib

我总是使用loadNibNamed方法将自定义视图加载到视图控制器中,但现在我试图避免在自定义视图之外调用该方法,以使其更具可重用性,以便在其他人使用我的时候自定义视图他只需要在没有loadFromNib的情况下实例化视图,例如:

var myView: MyView = MyView()

将此视图添加到视图控制器的视图就足够了,自定义视图会将nib加载到其自身内部。 我试图在Swift中做到这一点,在ObjC中我找到了类似这个答案的代码:UIView and initWithFrame and a NIB file. How can i get the NIB file loaded? 但是在swift中,我无法使用答案中使用的init:

- (id)initWithFrame:(CGRect)frame 
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code.
        //
        [[NSBundle mainBundle] loadNibNamed:@"MyView" owner:self options:nil];
        [self addSubview:self.view];
    }
    return self;
}

我有这个方法,它以无限循环结束:

override init(frame: CGRect) {
    super.init(frame: frame)
    self.loadFromNibNamed("MyView")
}

我还尝试在MyView中添加另一个视图作为IBOutlet,就像其他答案所说并使用所有内容一样:

@IBOutlet var view: UIView!

override init() {
    super.init()
    NSBundle.mainBundle().loadNibNamed("MediaPlayerView", owner: self, options: nil)
    self.addSubview(self.view)
}

override init(frame: CGRect) {
    super.init(frame: frame)
    NSBundle.mainBundle().loadNibNamed("MediaPlayerView", owner: self, options: nil)
    self.addSubview(self.view)
}

required init(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    NSBundle.mainBundle().loadNibNamed("MediaPlayerView", owner: self, options: nil)
    self.addSubview(self.view)
}

但仍然遇到了无限循环的错误。

我无法找到一个好的解决方案而且它让我发疯!有人可以帮帮我吗?谢谢!

2 个答案:

答案 0 :(得分:0)

我认为更干净的方法是使用默认初始值设定项,但使用您自己的像这样

override init(frame: CGRect, shouldLoadFromNib: Bool) {
    super.init(frame)
    guard shouldLoadFromNib else {
         return
    }
    NSBundle.mainBundle().loadNibNamed("MediaPlayerView", owner: self, options: nil)
    self.addSubview(self.view)

}

这样,当您从其他地方实例化它时,您会立即看到这不仅仅是某些UIView的普通旧实例,而是它有副作用(视图将是从笔尖加载

我不确定super.init(frame)电话,loadNibNamed也可能会为您拨打电话,因此您可能需要查看

答案 1 :(得分:0)

您获得了无限循环,因为loadNibNamed(_,owner:,options:)调用了init,因此请尝试再次加载笔尖,再次依次加载......试试这个:

Swift 4

var contentView: UIView?

// MARK: Initializers

override init(frame: CGRect) {
    super.init(frame: frame)
    configureView()
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    configureView()
}

override func prepareForInterfaceBuilder() {
    super.prepareForInterfaceBuilder()
    configureView()
}

override func awakeFromNib() {
    super.awakeFromNib()
    configureView()
}

// MARK: Config Functions

func configureView() {
    guard let view = defaultView() else { return }
    view.frame = bounds
    view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
    addSubview(view)
    contentView = view

    updateView()
}

func defaultView() -> UIView? {
    // Create view from a nib with the same name
    let nibName = String(describing: type(of: self))
    let bundle = Bundle(for: type(of: self))
    let nib = UINib(nibName: nibName, bundle: bundle)

    return nib.instantiate(withOwner: self, options: nil).first as? UIView
}

这段代码的作用是从笔尖加载视图,然后将其添加到视图内的子视图中。

这也可以在将视图添加到其他xib上时添加@IBDesignable并且可以使用