1

Followup on this question.

I have an app, where the main view has one button, and a file 'popup.xib' which is now empty (Just a view, no buttons, no labels, nothing). And I want it to popup when I press the button. For some reason I get the following error whenever I press the button:

... this class is not key value coding-compliant for the key view.'

I have read that this is because of outlets from the NIB which have been deleted or changed, that's why I removed all objects and what to display an empty view. But I still get this error.

My code:

ViewController.swift

import UIKit

class ViewController: UIViewController {

    @IBAction func showPopup(sender: AnyObject) {
        var x = UINib(nibName: "Popup", bundle: nil);
        println(x)
        var y = x.instantiateWithOwner(nil, options: nil)

        println(y)

        var z = y[0] as? PopupViewController

        println(z)
        z!.show(self.view)
    }


}

PopupViewController.swift

import UIKit


class PopupViewController : UIViewController {

    func show(tView : UIView) {
        tView.addSubview(self.view)
        self.view.backgroundColor = UIColor.redColor()
    }

}

The output:

<UINib: 0x7ff822412f90>
2015-02-02 15:47:57.870 tttt[5437:179808] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<NSObject 0x7ff822553ec0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key view.'
*** First throw call stack:

Update

enter image description here


Update 2

I continued tweaking stuff according to the answers and comments, and got if I do var y = x.instantiateWithOwner(PopupViewController(), options: nil) the line get executed OK. But then I get back an array containing a UIView, not a UIViewController. Therefore the last line z!.show(self.view) causes a crash. I know it creates the right nib, cause the properties (e.g. alpha value) that I changed appear in the text output from println(y) correctly.

So my question now is: What should I pass as the owner into instantiateWithOwner?

Community
  • 1
  • 1
Ramzi Khahil
  • 4,932
  • 4
  • 35
  • 69
  • Did you try to use self as owner parameter. – Duyen-Hoa Feb 02 '15 at 14:33
  • Tried now, variable z is still nil. – Ramzi Khahil Feb 02 '15 at 14:42
  • Actually y is still a list of one `UIView`, so the cast does not work and nil is used. – Ramzi Khahil Feb 02 '15 at 14:43
  • rename the .xib to PopupViewController.xib, and call var x = UINib(nibName: "PopupViewController", bundle: nil); and delete the instantiateWithOwner part. – Dávid Kaszás Feb 02 '15 at 15:32
  • it's strange your problem. are your viewcontroller and .xib included in the target that you run with? – Duyen-Hoa Feb 02 '15 at 16:24
  • I know it's strange. I probably missed the most obvious thing. But I just checked. They are marked – Ramzi Khahil Feb 02 '15 at 16:27
  • 1
    Try to use: var nibs = NSBundle.mainBundle().loadNibNamed("NibNameHere", owner: self, options: nil); Then if nibs is not nil (it find your nib), get the first in that array. – Duyen-Hoa Feb 02 '15 at 16:47
  • @tyt_g207 Thanks for the idea, unfortunately, this also gives me an array containing a UIView, not a UIViewController. :-\ – Ramzi Khahil Feb 03 '15 at 10:09
  • @tyt_g207 I Made it work thanks to you. It needed some weird tweaks but now have a working example. – Ramzi Khahil Feb 03 '15 at 10:27
  • You are welcome. Nice to see it works. So, what are the tweaks? – Duyen-Hoa Feb 03 '15 at 14:13
  • At the end I didn't use `loadNibNamed` but the regular option presented at `Nerkyator`s answer. But replaced the owner instead of nil it is an instance of whatever class I want, and then use `presentViewController` to show it. I have no idea why this works. You solution made it show, but never responded properly. Anyway I have a working example. So many thanks. – Ramzi Khahil Feb 05 '15 at 14:48

3 Answers3

0

Check what kind of class you have as the file owner. The error seems to be saying that it's trying to link the view in your .xib to a plain NSObject which, of course, has no view property.

If you don't want an owner that links to the view, make sure that there are no view outlets. Also verify that the file's owner is a type of object that really exists.

Phillip Mills
  • 30,888
  • 4
  • 42
  • 57
  • Done that. See my update. What do you mean "object that really exists"? I have checked that there is no typo if that's what you mean. – Ramzi Khahil Feb 02 '15 at 14:13
  • Using your image as an example, I mean being sure that there really is a `PopupViewController` in the project (and that it, or something it's derived from, really has a `view` property). The reference to `NSObject` in the error message is really suspicious. – Phillip Mills Feb 02 '15 at 14:16
  • Is there any chance that the `PopupViewController.swift` file is not marked as part of the target you're building? – Phillip Mills Feb 02 '15 at 14:20
  • It is `PopupViewController.swift` and it's marked for building. Anyway see my edit. – Ramzi Khahil Feb 02 '15 at 14:27
0

You have to connect the File's Owners view property to the view in the interface builder.

enter image description here

Dávid Kaszás
  • 1,877
  • 1
  • 16
  • 20
0

Maybe there are some messing in connections between StoryBoard XIB and swift classes (sorry I'm not with my iMac and I can't say you to send me a zip of the project) I'll write here steps I usually follow to accomplish such things, hoping this can help:

  • Create Xib file in your project. Place items on it as always. (ex: MyViewController.xib)
  • Create a new Swift class (name usually is the same as the Xib) (ex: MyViewController.swift)
  • In Interface Builder, select the xib, select the UIViewController and choose View > Utilities > Show Identity Inspector.
  • In the "Class" field select your custom swift class (MyViewController.swift)
  • Connect IBOutlets and IBActions if you need to
  • In MyViewController.swift add this extension:

    extension UIViewController {
    class func loadFromNibNamed(nibNamed: String, bundle : NSBundle? = nil) -> UIViewController? {
        return UINib(
            nibName: nibNamed,
            bundle: bundle
            ).instantiateWithOwner(nil, options: nil)[0] as? UIViewController
        }
    }
    
  • In your MainController add this line wherever you need it (in button click or other places)

    var x = MyViewController.loadFromNibNamed("MyViewController") as MyViewController
    

X now is instance of your MyViewController and Xib files is already loaded.

Nerkyator
  • 3,976
  • 1
  • 25
  • 31
  • "Create Xib file in StoryBoard" - What do you mean? I have Main.storyboard and Popup.xib - two different files. – Ramzi Khahil Feb 02 '15 at 15:12
  • I'm sorry, I'm at work and typos are always hunting for me. I mean _Create a Xib file in your project_. I edit my answer.. – Nerkyator Feb 02 '15 at 15:14