1

I am trying to load a xib filed called "AddProgramView" using loadnibnamed when a user presses a button. I created the xib in storyboard, placed various subviews within the xib view, and hooked up outlets to a corresponding swift file named AddProgramView. When I load the xib, none of the subviews appear. They are all missing. Help? Here's my code

Within my main view controller:

@IBAction func addProgram(sender: UIButton) {

    if let _ = addProgramView {
        addProgramView!.frame = CGRectMake(0, self.window!.frame.origin.y + self.window!.frame.height, self.window!.frame.width, CGFloat(325))
    }
    else {
        let addProgramViews = NSBundle.mainBundle().loadNibNamed("AddProgramView", owner: self, options: nil)
        addProgramView = addProgramViews.first as? AddProgramView

        addProgramView!.frame = CGRectMake(0, self.window!.frame.origin.y + self.window!.frame.height, self.window!.frame.width, CGFloat(325))

        window?.addSubview(addProgramView!)
    }

    window?.bringSubviewToFront(addProgramView!)

    UIView.animateWithDuration(0.3, delay: 0.0, options: UIViewAnimationOptions.CurveEaseOut, animations: {
        self.addProgramView!.frame.origin.y -= CGFloat(325)
        }, completion: nil)
}

The AddProgramView.swift file:

class AddProgramView: UIView {


    @IBOutlet weak var nameField: UITextField!
    @IBOutlet weak var cancelButton: UIButton!

    @IBOutlet weak var instructionsLabel: UILabel!
}
Justin Leonard
  • 71
  • 1
  • 11

2 Answers2

6

First check, if you have your class name declared in the view itself, not in the file owner.

class name

If not, do it. Then try it again.

Another option is to create IBOutlet in your AddProgramView.swift

@IBOutlet var contentView: UIView!

and remove the class name from the view and add it to File's Owner.

owner's class name

Connect contentView by right-clicking at the File's owner:

enter image description here

Then create init methods like this:

class AddProgramView: UIView {
    @IBOutlet var contentView: UIView!

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

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

    func commonInit() {
        NSBundle.mainBundle().loadNibNamed("AddProgramView", owner: self, options: nil)
        self.addSubview(self.contentView)
        self.contentView.frame = self.bounds
    }
}

And now you can use the AddProgramView wherever you want. Either by init(frame:)

let addProgramView = AddProgramView.init(frame: CGRectMake(0, 0, 320, 30))

or you can use them directly inside storyboard by adding UIView and set them class to AddProgramView (No extra line of code, storyboard will call init(coder:) for you)

storyboard

I've created example project for you - CustomView project

Aleš Oskar Kocur
  • 1,189
  • 1
  • 10
  • 26
  • I had already tried the first option correctly. So I tried the second option. Am I supposed to add each IBOutlet within commonInit(), or just the contenView, which has all of my subviews? In particular, let's say i have an IBOutlet called myTextField that is a subview within contentView. Am I supposed to add myTextField as a subview of contentView within commonInit()? I'm guessing not, but it's not working. There are two issues: – Justin Leonard Sep 23 '15 at 10:08
  • I had already tried the first option correctly. So I tried the second option. Am I supposed to add each IBOutlet within commonInit(), or just the contenView, which has all of my subviews? I'm guessing not, but it's not working. There are two issues: (1) the placement of the contentView is offset to the left from where it is supposed to be. Calling self.contentView.bounds = self.bounds not working right (2) the subviews still don't appear by just adding contentView as a subview within commonInit(). If I add my subviews explicitly, they lose all constraints specified in the xib file. Any ideas? – Justin Leonard Sep 23 '15 at 10:14
  • I have updated the answer for you. You should use frame instead of bounds. There is also the example project, take a look. – Aleš Oskar Kocur Sep 23 '15 at 11:48
  • Switching to frame solved issue (1). Your test project worked. But I swear I am doing exactly the same thing, yet my project does not work. Here is a slimmed down version of my project. Can you identify what's wrong? https://dl.dropboxusercontent.com/u/35854077/TestXib.zip – Justin Leonard Sep 23 '15 at 12:46
  • I've found a problem. You have to connect the first view in stack. https://www.dropbox.com/s/t0ltdlg9p5n5gzc/Screenshot%202015-09-23%2015.14.26.png?dl=0 . Then your view will be loaded properly. Nevertheless, your solution of showing view is bad. You should create another controller and present him as modal. – Aleš Oskar Kocur Sep 23 '15 at 13:17
  • Thanks! That did it. I want to be able to reuse a calendar that i have displayed in the main view, rather than having to reload a whole new view and new calendar. I think that creates a more seamless user experience. Anyway, thanks again! – Justin Leonard Sep 23 '15 at 13:29
  • Thanks for answer, I one doubt why we need to self.addSubview(self.contentView) after init view with nib. – Bhavesh Patel Aug 10 '18 at 07:51
  • @AlešOskarKocur What if I have to add that custom view programmatically on the view instead of creating a dummy view. – Jarvis The Avenger Dec 19 '20 at 03:40
1

Double-check that you don't have a size class specified in your xib file. It should say Any/Any at the bottom of the editor window.

northernman
  • 1,374
  • 15
  • 18