22

I have a project that is all in Objective C, except for my view controller, which is in Swift.

When I run it, i get the error

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[UIViewController _loadViewFromNibNamed:bundle:] loaded the "..." nib but the view outlet was not set.'

So I opened up my nib file, look at "File's Owner", and I see that the view does not even show up as an outlet at all.
For my old view controller (objective c), the view outlet does show up.

In my Swift view controller, I tried overriding the "view" variable from UIViewController in order to force it to be an @IBOutlet, but it complained about the "view" variable being of type UIView, complained about UIView?, and complained about UIView!.

Here are simplified versions of

my AppDelegate.h

#import <UIKit/UIKit.h>

@class MyViewController;
@class MyViewControllerSwift;

@interface MSAppDelegate : UIResponder <UIApplicationDelegate>
{
}

@property (strong, nonatomic) UIWindow *window;

@property (strong, nonatomic) UIViewController *viewController;

@end

AppDelegate.m

#import "MyAppDelegate.h"

#import "MyViewController.h"
#import "MySwift-Swift.h"
#import <UIKit/UIKit.h>

@implementation MyAppDelegate

static BOOL USE_SWIFT_VIEW_CONTROLLER = YES;

- (void)dealloc
{
    [_window release];
    [_viewController release];
    [super dealloc];
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
    // Override point for customization after application launch.

    id viewControllerPtr = nil;
    if(USE_SWIFT_VIEW_CONTROLLER)
    {
        viewControllerPtr = [MyViewControllerSwift alloc];
    }
    else
    {
        viewControllerPtr = [MyViewController alloc];
    }

    UIViewController* vController = nil;
    if(USE_SWIFT_VIEW_CONTROLLER)
    {
        vController = [[viewControllerPtr initWithNibName:@"MyViewControllerSwift" bundle:nil] autorelease];
    }
    else
    {
        vController = [[viewControllerPtr initWithNibName:@"MyViewController" bundle:nil] autorelease];
    }

    self.viewController = vController;
    self.window.rootViewController = self.viewController;
    [self.window makeKeyAndVisible];

    return YES;
}

ViewController.swift

import Foundation
import AVFoundation

@objc class MyViewControllerSwift : UIKit.UIViewController {

    var player : AVFoundation.AVAudioPlayer?;

    @IBOutlet weak var myTextView : UITextView!;

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

    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
        super.init(nibName:nibNameOrNil, bundle:nibBundleOrNil);
    }

    override func viewDidLoad() {
        super.viewDidLoad();

        println("Using MyViewControllerSwift");
    }

    deinit {
        //TODO
    }
}

What do I need to do to get my view to display?

Thanks.

(Yes, this is a similar question to Loaded nib but the view outlet was not set - new to InterfaceBuilder but the view outlet does not show up. )

Community
  • 1
  • 1
cowlinator
  • 7,195
  • 6
  • 41
  • 61

6 Answers6

44
  • First - set custom class in your nib file (File's Owner -> third icon -> custom class : YourViewController )
  • Second - the last icon in file's owner -> link (drag) the "view" property to the interface view

Init your ViewController like so:

YourViewController(nibName: "YourViewName", bundle: nil)

It will work. Don't do any manipulations with View.

user3677173
  • 2,559
  • 2
  • 17
  • 16
  • I have done so. I have reverted all manipulations of view and there are no references to it in my code. However, when I select the "File's Owner" object and open the Connections Inspector, there is no "view" property. http://i.pictr.com/4v475ryo0i.png – cowlinator Sep 29 '14 at 18:59
  • Also, I should point out that I need to initialize my ViewController using objective-c, not swift, so I am actually initializing it like this: [[viewControllerPtr initWithNibName:@"MyViewControllerSwift" bundle:nil] autorelease]; where viewControllerPtr is a correctly allocated id. – cowlinator Sep 29 '14 at 19:02
  • 1
    Look what you might do. Create view from the scratch, don't do anything with it. Just click on file's owner, assign the controller, and then drag view. It should work 100%. – user3677173 Sep 30 '14 at 06:50
  • My guess is that you removed the according view accidentally. – user3677173 Sep 30 '14 at 06:52
  • https://www.dropbox.com/s/16e0itxwujbo1sb/Screenshot%202014-09-30%2009.51.41.png?dl=0 here is the screenshot. – user3677173 Sep 30 '14 at 06:52
  • Thank you, user. Creating the viewController swift file from scratch, I noticed the view was back. I copy-pasted all the code back in and everything worked. – cowlinator Sep 30 '14 at 19:42
  • Is there no way to re-add the view if it gets removed, short of recreating the whole file? – cowlinator Sep 30 '14 at 19:43
  • I am not sure about that. But certainly you can add as many views as you want. Just drag em, it should appear on the list. – user3677173 Oct 01 '14 at 12:03
  • Works, Thank you.! Only question is that I'm using an EmptyNib. Now I've 5 ViewControllers, all of them have a tableView. I want to use this EmptyNib for all of these 5 ViewControllers coz I don't have any outlets connected. How can I do it.? coz If I connect one class using this approach, then that EmptyNib won't act as Generic for all 5 ViewControllers. – Yash Bedi Sep 19 '19 at 12:31
13

If you have tried everything and you still get this error, try re-creating the class file from scratch but remember to select the "Also create XIB file" check box. This will auto link up a few items that are not linked when creating these files separately. After this is created, you can likely cut and paste everything onto the new XIB and it should work fine.

I am finding this issue specifically with creating files separately in Swift.

Travis M.
  • 10,930
  • 1
  • 56
  • 72
1

I had the same problem , my 2nd view on my view controller couldn't load . I changed the view's name in property(as I had previously given "View"). Your existing view controller already had references to the view on top of it with the same name(View). Hence the error . Try changing the outlet names . It worked perfect in my case .

user5553647
  • 199
  • 2
  • 13
1

Originally I ran into this same issue when I had an empty .xib and dropped in a UIViewController.

My fix was to remove the UIViewController and just add a UIView instead. I made the File's Owner (under Placeholders) Custom Class -> Class the name of the UIViewController class that would contain all the controller logic. I connected the UIView in the .xib file to the view Placeholder -> File's owner -> Outlets.

Maybe Apple/Xcode is trying to enforce a more strict MVC design by removing the UIViewController from everything but storyboard? I tried to follow the advice of many other posts I saw in trying to connect my UIViewController's view (of the UIViewController I originally dropped into the .xib) but it wouldn't connect no matter whether I made the Class type in File's Owner or for the UIViewController the same as my custom class.

This is the only thing that worked for me in Xcode 11.0

SpicyNinja1010
  • 177
  • 2
  • 5
0

I found on chinese forum that it could be happen when you have similar names for ViewController and view from XIB.

Example SpecialOfferViewController and SpecialOfferView

I renamed

SpecialOfferViewController and OfferView and error has gone!!!

Leonif
  • 466
  • 4
  • 17
0

I had a xib file named FooView and a view controller class named FooViewController.

FooVew was not intended to the be the root view of FooViewController, only a subview. Yet, UIViewController's default behavior is to automatically attempt exactly that. And thus, my app would crash with this error at the first point that my controller's view was accessed.

This behavior can be avoided using one of:

  1. Rename your controller class or the xib file to dissociate them
  2. override var nibName: String? { nil }
  3. override func loadView() and assign to view yourself

I went with 2 as it seemed the least likely sneak back to bite me later.

Nathan Hosselton
  • 1,089
  • 1
  • 12
  • 16