0

I've pulled up an old project trying to reuse some functionality. I've created a nib with a UIView subclass. In the original, working version I didn't need to set File's owner in IB. However, I'm receiving errors alluding that I now need to do so (Xcode 7): loaded the "TipView" nib but the view outlet was not set.

So I proceeded to hook the File's owner up to the view controller that is responsible for setting up the view. Here's the relevant code from the View Controller:

class TipViewController: UIViewController {

  private let kTipViewHeight: CGFloat = 400
  private let kTipViewWidth: CGFloat = 300

  override func viewDidLoad() {
    super.viewDidLoad()

    if let tipView = createTipView() {
        let center = CGPoint(x: CGRectGetWidth(view.bounds)/2, y: CGRectGetHeight(view.bounds)/2)
        tipView.center = center
        view.addSubview(tipView)
    }
  }

  func createTipView() -> UIView? {
    if let view = UINib(nibName: "TipView", bundle: nil).instantiateWithOwner(nil, options: nil).first as? TipView {
        view.frame = CGRect(x: 0, y: 0, width: kTipViewWidth, height: kTipViewHeight)
        return view
    }
    return nil
  }

}

extension UIViewController {
  func presentTips(tips: [Tip], animated: Bool, completion: (() -> Void)?) {
    let controller = TipViewController()
    controller.modalTransitionStyle = .CrossDissolve
    presentViewController(controller, animated: animated, completion: completion)
  }
}

I tried setting instantiateWithOwner to: .instantiateWithOwner(self, options: nil).first (changed nil to self) also to no avail.

This is the relevant presenting view controller code:

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)
    presentTips([], animated: true, completion: nil)
}

The UIView subclass doesn't do anything out of the ordinary, so I haven't bothered to include its code.

When I make the changes requested - add TipViewController as the nib's File owner and hook up its view outlet to the nib view - I get a range of error messages depending on which configurations I take ranging from:

this class is not key value coding-compliant for the key view. Can't add self as subview

Not sure why I was able to use a nib without a file's owner in Xcode 6, but am not able to do so as of Xcode 7 - haven't found any material or release notes related to the change, so I'm a little stumped for now.

Any help is very much appreciated.

Kyle G
  • 4,347
  • 4
  • 26
  • 39

1 Answers1

2

So I proceeded to hook the File's owner up to the view controller that is responsible for setting up the view

No, you were right the first time. Your problem is that there was a bug having to do with nib names in iOS 8, it was fixed in iOS 9, and you got caught in the net because the bug, ironically, protected you from stumbling across this issue previously.

Do this:

  • Leave the File's Owner configured as an NSObject.

  • Do not hook up any outlets from the File's Owner to the view in the nib; if there is such an outlet, delete it.

  • Load the nib with a nil owner, just as you are doing.

  • (Ready for this? This is the key:) Rename the nib. Don't call it TipView.xib. That name was what caused the whole issue you've been trying to work around. Call it, let's say, TipViewNib.xib. Revise your code accordingly, i.e. load the nib with nibName: "TipViewNib".

  • Clear all caches including the simulator version (as I explain here: How to Empty Caches and Clean All Targets Xcode 4) to get rid of the bad nib (the one with the name TipView.xib).

Your problems will then evaporate like morning mist.

Community
  • 1
  • 1
matt
  • 515,959
  • 87
  • 875
  • 1,141
  • Thanks for the input @matt. This actually didn't resolve it for me. But I'm sure it will resolve it for others. – Kyle G Mar 20 '16 at 16:12
  • I'm sure what I'm saying is right. Note that you may need to _clear all caches_ before this will work, in order to get rid of the "bad" nib (the one with the TipView name). See http://stackoverflow.com/questions/5714372/how-to-empty-caches-and-clean-all-targets-xcode-4/6247073#6247073 If that doesn't work, can you post at least the relevant piece of the project on github? I'll fix it for you. – matt Mar 20 '16 at 16:13
  • Added clearing the caches as a step. That's crucial. You really screwed things up by using this nib name and it's going to take some work to unscrew them. – matt Mar 20 '16 at 16:16
  • Shoot. I'm sorry. You were 100% correct. I cleared derivedData and simply changing the nib name allowed it to compile without error. What a crazy bug! Do you have an open radar for this that I can dupe? – Kyle G Mar 20 '16 at 16:29
  • It's not a bug now. It was a bug in iOS 8. That bug is closed - it was fixed in iOS 9. – matt Mar 20 '16 at 16:30
  • What you see in 9.3 is _not a bug_. The problem is _your_ mistake: you must not give a nib the same name as a view controller unless you know the special meaning that that has (and you want that special meaning). The bug is that you ever got away with your wrong behavior (in iOS 8). – matt Mar 20 '16 at 16:49