Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Initialize Swift subclass of UIView, designed in .xib
// Create CustomView.xib, set File's Owner to CustomView.
// Link the top level view in the XIB to the contentView outlet.
class CustomView : UIView {
@IBOutlet private var contentView:UIView?
// other outlets
override init(frame: CGRect) { // for using CustomView in code
super.init(frame: frame)
self.commonInit()
}
required init?(coder aDecoder: NSCoder) { // for using CustomView in IB
super.init(coder: aDecoder)
self.commonInit()
}
private func commonInit() {
Bundle.main.loadNibNamed("CustomView", owner: self, options: nil)
guard let content = contentView else { return }
content.frame = self.bounds
content.autoresizingMask = [.flexibleHeight, .flexibleWidth]
self.addSubview(content)
}
}
@y00s

This comment has been minimized.

Copy link

y00s commented Dec 14, 2015

Hi,
Thanks for code.

I tried to use it as following :

override public init(frame: CGRect)
{
    super.init(frame: frame)

    self.commonInit()
}

required public init?(coder aDecoder: NSCoder)
{
    super.init(coder: aDecoder)
    self.commonInit()
}

private func commonInit() {
    NSBundle(forClass: CustomController.self).loadNibNamed("CustomController", owner: self, options: nil)
    guard let content = view else { return }
    content.frame = self.bounds
    content.autoresizingMask = [.FlexibleHeight, .FlexibleWidth]
    self.addSubview(content)
}

but every time that loadNibName line done it calls to - init(coder) function
and it makes infinity loop with commonInit..

please help

---- EDIT-----

I resolved my issue
In the document outline, you should only set the File's Owner to your custom class,
and leave the top level "view" object below as nothing.

@dnsmob

This comment has been minimized.

Copy link

dnsmob commented Feb 9, 2016

👍 🍻

@jackywang135

This comment has been minimized.

Copy link

jackywang135 commented Feb 12, 2016

Why do you need to addSubview when the IBOutlet already makes the contentView a subview of the superview?

@ghost

This comment has been minimized.

Copy link

ghost commented Mar 4, 2016

I did everything and it runs fine. However, my constraints set in the xib file don't carry over properly. I have a label that is supposed to be 8 from the top and it's actually something like 30 from the top. I'm setting the custom view as a tableview tableheaderview.

@jasonwiener

This comment has been minimized.

Copy link

jasonwiener commented Apr 9, 2016

thanks a ton for this...

@leancmscn

This comment has been minimized.

Copy link

leancmscn commented Apr 12, 2016

not support autolayout for different devices

@nicolas-miari

This comment has been minimized.

Copy link

nicolas-miari commented Jun 9, 2016

Great, thanks for posting this.

@guttentag

This comment has been minimized.

Copy link

guttentag commented Jun 9, 2016

great stuff!
works great!

@leandropjp

This comment has been minimized.

Copy link

leandropjp commented Nov 23, 2016

Great, Thanks!

@joelklabo

This comment has been minimized.

Copy link

joelklabo commented Dec 21, 2016

Thanks! It's crazy how difficult it is to find information on how to do this

@girishvr

This comment has been minimized.

Copy link

girishvr commented Jan 4, 2017

Use this to break the infinite loop.

 required init?(coder aDecoder: NSCoder) { // for using CustomView in IB
        super.init(coder: aDecoder)
         if self.subviews.count == 0{
             self.commonInit()
         }
    }
@dbleiweiss13

This comment has been minimized.

Copy link

dbleiweiss13 commented Jan 7, 2017

how do you link top level view in the xib to the content view outlet

@Sesadev

This comment has been minimized.

Copy link

Sesadev commented Mar 25, 2017

class CustomHeader: UIView {

var view:UIView!

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

required init(coder aCoder: NSCoder) {
    super.init(coder: aCoder)!
    setup()
}

func setup() {
    view = self.loadViewFromNib()
    view.frame = bounds
    view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
    addSubview(view)
}

func loadViewFromNib() -> UIView {
    
    return UINib(nibName: "CustomHeader", bundle: nil).instantiate(withOwner: nil, options: nil)[0] as! UIView
    
}

Simply add class type (Ex.CustomHeader) in Xib file of where you are going to use this custom class. it worked fine for me

@omarfouad

This comment has been minimized.

Copy link

omarfouad commented Apr 6, 2017

Is it possible to have this in an extension (swift 3)? I don't seem to be able to come up with a working one. Ideas?

@Ohad-Maor

This comment has been minimized.

Copy link

Ohad-Maor commented Aug 6, 2017

Just use NibDesignable

@denis631

This comment has been minimized.

Copy link

denis631 commented Oct 2, 2017

Don't try to get the first view. If you do it, the iboutlets won't be set anyway, which is not what you what. Rather do this:

import UIKit

class CustomView: UIView {
    @IBOutlet weak var contentView: UIView?
    @IBOutlet weak var anotherSubviewOfContentViewHere: UIView?
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        nibSetup()
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        nibSetup()
    }
    
    func nibSetup() {
        Bundle.main.loadNibNamed(String(describing: CustomView.self), owner: self, options: nil)
        
        guard let contentView = contentView else { return }
        self.addSubview(contentView)
    }
}
@trupti2088

This comment has been minimized.

Copy link

trupti2088 commented Jan 10, 2018

It goes into an infinite loop. No solution seems to be working for creating a simple custom UIView!!!!!

@yunchiri

This comment has been minimized.

Copy link

yunchiri commented Jan 14, 2018

It goes into an infinite loop too

@ovyhlidal

This comment has been minimized.

Copy link

ovyhlidal commented Mar 6, 2018

Infinite loop is caused by not setting FileOwner or remove custom class name in top level view. Top level view should be just UIView. All outlets has to be connected from FileOwner.

@StarWars

This comment has been minimized.

Copy link

StarWars commented May 1, 2018

Here is the setup for all you guys experiencing infinite loop:

  1. Open your xib file
  2. Press File's Owner -> Utilities pane (right Xcode pane) -> 3rd "tab" -> Custom Class -> Set Class to the name of your *.swift/*.m file
  3. Press topmost view -> remove Custom Class in the same menu as in step 2.
  4. If your *.swift / *.m file already had the outlets configured, you'll notice, that they are not connected (you can see that in the 6th tab of the right Xcode pane). To fix that proceed to steps 5 and 6.
  5. Delete all the iboutlets you've had configured for your subviews.
  6. Connect File's Owner's outlets to your subviews
@Abdulaziz1993

This comment has been minimized.

Copy link

Abdulaziz1993 commented Sep 18, 2018

thanks for the code

@sudebsm

This comment has been minimized.

Copy link

sudebsm commented Sep 26, 2018

Hi all
I need to send extra two parameters in CustomView class from the viewcontroller class , How this is possible.

@Bhide

This comment has been minimized.

Copy link

Bhide commented Jan 31, 2019

There's a memory leak shown at 'Bundle.main.loadNibNamed'

screen shot 2019-01-31 at 11 43 18 am

@maneesh888

This comment has been minimized.

Copy link

maneesh888 commented Nov 16, 2019

I think we are on the same page, I want to create a custom view with IBOutlets. And I want to create it in such a way that it can directly use in storyboard. But it seems to impossible, when init with coder initialise a view, the IBOutlets are nil. If I use a different method using files owner , awake from nib will never execute, here. The sad part is that, the dilemma is to just load a view to screen. Anyone have a comment?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.