IBOutlet is nil, but it is connected in storyboard, Swift

谁说胖子不能爱 提交于 2019-11-26 20:10:34

Typically this happens because your view controller hasn't loaded its view hierarchy yet. A view controller only loads its view hierarchy when something sends it the view message. The system does this when it is time to actually put the view hierarchy on the screen, which happens after things like prepareForSegue:sender: and viewWillAppear: have returned.

Since your VC hasn't loaded its view hierarchy yet, your outlets are still nil.

You could force the VC to load its view hierarchy by saying _ = self.view.

Have you tried running Product > Clean. Solved a very similar problem for me.

Did you instantiate your view controller from a Storyboard or NIB, or did you instantiate it directly via an initializer?

If you instantiated your class directly with the initializer, the outlets won't be connected. Interface Builder creates customized instances of your classes and encodes those instances into NIBs and Storyboards for repeated decoding, it doesn't define the classes themselves. If this was your problem, you just need to change the code where you create your controller to instead use the methods on UIStoryboard, or UINib.

The storyboard wasn't recognizing any further UI things I added to it. At run time all the references were nil. So I cleared my derived data folder and then those connections worked again.

rounak

This was happening to me with my custom collection view cell. Turns out I had to replace my registerClassforReuseIdentifier method with registerNib. That fixed it for me.

In my case, it happened because I overriden the loadView method in my ViewController subclass, but forgot to add [super loadView]

-(void)loadView {
// blank
}

When you override the loadView method, the it is your responsibility to init your subviews. Since you override it, the views from interface builder do not get the chance to convert to cocoa objects and thus outlets remain nil.

If you implement loadView in your view controller subclass, then it becomes your responsibility load the UI elements from from storyboard/xib into code.

Or just call

[super loadView];

So that the superclass gets the chance to load storyboard/xib into code.

This happened for me because I was accidentally instantiating my view controller directly instead of instantiating it through the storyboard. If you instantiate directly via MyViewController() then the outlets won't be connected.

You can call controller.view to force to load the view to initialize the IBOutlets, then you will be able to assign the values.

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
    if (segue.identifier == "identifier") {
        let controller = segue.destinationViewController as! YourController
        let _ = controller.view //force to load the view to initialize the IBOutlets

        controller.your_IBOutlet_property = xxx
        ...
        controller.delegate = self
    }
}

For me, this occurred when I accidentally declared my view controller's class as

class XYZViewController: UINavigationController {
}

(ie as a UINavigationController not a UIViewController).

Xcode doesn't pick up on this mistake, the class seems to build fine, and override functions such as viewDidLoad, viewWillAppear, etc. all work correctly. But none of the IBOutlets get connected.

Changing the declaration to

class XYZViewController: UIViewController {
}

fixed it completely.

I encounter this problem recently! Here is my thought. The problem is not about you storyboard or any link issue. It is about how you initiate your ViewController. Especially when you are using Swift.(There is barely nothing in the editor when you create a class file)

By simply using the init() from super class can not initiate anything you worked with story board. So what you need to do is changing the initialisation of the ViewController. Replace let XXViewController = XXViewController() by let XXViewController = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle()).instantiateViewControllerWithIdentifier("XXViewController") as! XXViewController This tells the program to go to the storyboard find XXViewController and initiates all IBOutlet in your storyboard.

Hope this help~ GL

For Swift 3.

func configureView() {
    let _  = self.view
}

You need to load the view hierarchy first in order to instantiate the outlets in the storyboard. For this, you can manually call the loadView or loadViewIfNeeded methods.

Check your IBOutlet connection if it connected to the File owner or the view. There could be mistakes.

Other case:

Your outlets won't get set until the view controller's view is actually instantiated, which in your case is probably happening shortly after initWithNibName:bundle:—at which point they'll still be nil. Any setup you do that involves those outlets should be happening in your view controller's -viewDidLoad method.

For me, I had same error on a localized storyboard, an element was added in some locale and not in the other, so I had null reference for that element when switched to the missing element locale, I had to remove (redundant) localization for that storyboard using https://stackoverflow.com/a/42256341/1356559.

For me, this was crashing because containerView was nil.

Here is my code with Crash.

@IBOutlet private var containerView: UIView!  // Connected to Storyboard
override open func loadView() {
    containerView.addSubview(anotherView)
}

The missing thing was calling the super.loadView(). So adding it solved problem for me.

Fixed Code:

@IBOutlet private var containerView: UIView!
override open func loadView() {
    super.loadView()
    containerView.addSubview(anotherView)
}

I had a similar issue when I had previously added register(_:forCellReuseIdentifier:) for the custom cell after I had already defined the identifier in the storyboard. Had this code in the viewDidLoad() function. Once I removed it, it worked fine.

Yet another case I just ran into. I changed the name of my class for the UIViewController, but I forgot to change the name of the .xib file where the interface was built.

Once I caught this and made the file names reflect the class name, it was all good!

I hope that helps someone.

Got one more ...

If you have a custom class for a UITableViewCell but forget to specify Custom in the Style of the cell.

You can validate if the is view is loaded.

if isViewLoaded && view.window != nil {
 //self.annotationOptionsView.
}

If you instantiate view controller through programmatically. Then try creating it like below

let initialVC = self.storyboard?.instantiateViewController(withIdentifier: "InitialVC") as! InitialVC

instead of directly

let initialVC = InitialVC()

This worked for me.

In my case, the app started crashing all of a sudden. Debugging it revealed that all outlets were still nil at the time of viewDidLoad().

My app still uses nibs (not storyboards) for most view controllers. Everything was in place, all outlets wired properly. I double-checked.

We typically instantiate our view controllers as

let newVC = MYCustomViewController()

...which for some reason seems to work as long as the .xib is named the same as the view controller class (not sure how that works, though. We are not calling init(nibName:bundle:) with nil arguments, or overriding init() to do so on self like it is typically suggested...).

So I tried to explicitly call

 let newVC = MYCustomViewController(nibName: "MYCustomViewController", bundle: .main)

...only to be greeted with the runtime exception error:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Could not load NIB in bundle: 'NSBundle </Users/nicolasmiari/Library/Developer/CoreSimulator/Devices/3DA3CF21-108D-498F-9649-C4FC9E3C1A8D/data/Containers/Bundle/Application/C543DDC1-AE86-4D29-988C-9CCE89E23543/MyApp.app> (loaded)' with name 'MYCustomViewController''

And then, I saw it:

The "Target Membership" checkbox of the .xib file was unchecked.


Must have happened when resolving one of the frequent merge conflicts regarding the Xcode project file.

Apple definitely needs to come up with a project file format that is more SCM-friendly.

100% Working solution for creating ViewControllers from XIB without StoryBoards

  1. Create class CustomViewController : UIViewController
  2. Create view CustomViewControllerView.xib
  3. In CustomViewControllerView.xib in Interface Builder select Placeholders -> File's Owner
  4. In "Attributes inspector" set Class to CustomViewController
  5. In "Connections inspector" connect "view" to top-level view of xib (ensure top-level view's Class is not pointing to CustomViewController)
  6. In "Connections inspector" connect other outlets (if needed/exist)
  7. Create an instance of CustomViewController in parent view controller/App delegate

7.1.

// creating instance
let controller = CustomViewController()

7.2.

// connecting view/xib with controller instance
let bundle = Bundle(for: type(of: controller))
bundle.loadNibNamed("CustomViewControllerView", owner: controller, options: nil)

7.3.

// get/set outlets
controller.labelOutlet.text = "title"
controller.imageOutlet.image = UIImage(named: "image1")
Sandip Patel - SM
  1. select both .h and .m view controller files
  2. remove the reference of those files
  3. re-add the files to your project tree
  4. open the storyboard, eventually re-build the project

Accidently I subclassed my view controller with AVPlayerViewController instead of UIViewController. By replaying it to UIViewController things back normal. This should help.

No build cleaning (normal&full), removing derived data folders and quitting Xcode worked for me.

I had the same problem after copying a class (linked to a xib) to reuse it with another viewcontroller class (linked to a storyboard). I forgot to remove

override var nibName

and

override var nibBundle

methods.

After removing them, my outlets started to work.

EvGeniy Ilyin

I see you use ViewController!? in ViewController class you must use -viewDidLoad, not -awakeFromNib, -awakeFromNib use for UIView class

Check to see if you have any missing or disconnected outlets.

If you have two main.storyboards and you are making changes to the wrong one this can happen. This can happen anytime you connect an outlet from an uninstantiated storyboard.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!