1

I have been trying to figure this out for days and haven't had much luck :(

What I want to do is set the variable inside of an instance of a XIB (called BottomNav) that already exists in another ViewController, called "curX". I have come the closest with the following:

class Util: NSObject {
    class func loadNib() {
        let nib: BottomNav = Bundle.main.loadNibNamed("BottomNav", owner: self, options: nil)!.first as! BottomNav
        nib.curX = 10
    }
}

Here is the BottomNav Class:

class BottomNav: UIView {
    @IBOutlet var view: UIView!
    @IBOutlet weak var homeBtn: UIView!
    @IBOutlet weak var scroller: UIScrollView!
    @IBOutlet weak var scrollerContent: UIView!

    var curX = 32

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)!

        Bundle.main.loadNibNamed("BottomNav", owner: self, options: nil)
        self.addSubview(self.view)
    }

}

This passes the compiler with no warnings, but when it's ran I get a "this class is not key value coding-compliant for the key" error. This usually appears when there's an outlet that no longer exists, but this is definitely not the case, I've tested it with multiple XIBs that are already on the app, and had no problem loading in the first place via storyboards. I only get this error with "loadNibNamed".

Am I even on the right path here? My thought is maybe my Util class doesn't have access to Bundle or something?

Erick Maynard
  • 731
  • 6
  • 18
  • 1
    try to inspect connected iboutlets in that xib and remove not connected connection from that xib. – KKRocks May 02 '17 at 06:27
  • As I mentioned, this is definitely, 100% not the problem. It's been checked, double checked, tried on multiple XIBs. It even loads the first time when it's is done through the storyboard without issue. – Erick Maynard May 02 '17 at 06:28
  • can you please add your BottomNav class here? – Mahesh De Silva May 02 '17 at 06:32
  • Just added now. – Erick Maynard May 02 '17 at 06:36
  • see this : http://stackoverflow.com/a/5458188/3901620 – KKRocks May 02 '17 at 06:43
  • Again, I can guarantee this is not the issue. All outlets have been double checked (triple just now), and the File's owner is what it is supposed to be: BottomNav. It was not copy pasted. This was tested with multiple XIBs and is loading correctly in the storyboard. It is weird that I'm getting this error, as you are right that is usually the issue. – Erick Maynard May 02 '17 at 06:48
  • As a quick test, I went in and deleted all the IBOutlets (except for "view", obviously because you have to have that one) and it still returns the same error. – Erick Maynard May 02 '17 at 06:52

2 Answers2

7
class BottomNav: UIView {
    @IBOutlet var view: UIView!
    @IBOutlet weak var homeBtn: UIView!
    @IBOutlet weak var scroller: UIScrollView!
    @IBOutlet weak var scrollerContent: UIView!

    var curX = 32

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

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

    func commonInit(){

        Bundle.main.loadNibNamed("BottomNav", owner: self, options: nil)
        guard let content = view else { return }
        content.frame = self.bounds
        content.autoresizingMask = [.flexibleHeight, .flexibleWidth]
        self.addSubview(content)
    }

}

And when calling the instance, try the following.

        let instance = BottomNav()
        instance.curX = 30
Mahesh De Silva
  • 505
  • 8
  • 20
  • Ahh, yes this does work, but let instance= BottomNav() creates a new instance yes? I need to access an instance that already exists, is this possible? – Erick Maynard May 02 '17 at 07:08
  • I suppose I could replace the old instance with a new one, is that the way it should be done? – Erick Maynard May 02 '17 at 07:10
  • Fantastic, thank you so much! This made me realize a gap in my knowledge that I sort of knew but it hadn't clicked yet... when it comes to the lifecycle of views and view controllers. – Erick Maynard May 02 '17 at 07:31
2

Swift 3.0

I Think you get you solution from this. All the best

    var view: UIView!

    override init(frame: CGRect) {

        // call super.init(frame:)
        super.init(frame: frame)

        // 3. Setup view from .xib file
        xibSetup()
    }

    required init?(coder aDecoder: NSCoder) {

        // call super.init(coder:)
        super.init(coder: aDecoder)

        // 3. Setup view from .xib file
        xibSetup()
    }

    // MARK: - UI setup
    func xibSetup() {

        let nib = UINib(nibName: "BottomNav", bundle: nil)
        view = nib.instantiate(withOwner: self, options: nil)[0] as! UIView

        // use bounds not frame or it'll be offset
        view.frame = bounds

        // Make the view stretch with containing view
        view.autoresizingMask = [UIViewAutoresizing.flexibleWidth, UIViewAutoresizing.flexibleHeight]

        addSubview(view)
    }
Jaydeep Vora
  • 6,085
  • 1
  • 22
  • 40