3

I have a weird problem with my app. I load a VC at runtime with a NIB named "LoginViewController." That NIB has a bunch of outlets to UIView objects that are placed in the NIB like so:

enter image description here

At runtime I dynamically place those UIView objects as headers in my table view. Each separate UIView in this case (except for the one with the UITableView in it, on the right) is set as an IBOutlet like so. Each has a different name of course:

@property (strong, nonatomic) IBOutlet UIView *connectionInProgressView;

Now, in my VC's viewDidLoad method I run through all four of these separate views and ensure they exist by writing to the log:

NSLog(@"connection in progress view: %@", self.connectionInProgressView);

My problem is this: self.connectionInProgressView is nil on iPad and not nil on iPhone. All the other views regardless of platform are NOT nil and are instantiated. I'm running this in the simulator on iOS 5.0, 5.1 and 6.1. I can recreate the issue on all iPad simulators. My app works just fine and loads the view with the spinner on iPhone, but on iPad it can't load that view because it's nil! Why!?

I have tried the following:

  • Checking that my NIB's File's Owner points to the proper view
  • That the self.connectionInProgressView doesn't point to any other IBOutlet
  • Checking that all the other sub views are hooked up the same way as the offending view. They are.
  • Deleting self.connectionInProgressView and re-creating it after removing all its NIB connections.
  • Removing the activity indicator from the view and loading just a view with a UILabel inside. No luck, its not the activity indicator.
  • Checked for any code in the VC that might reference self.connectionInProgressView. There is none (other than it's nil statement in viewDidUnLoad).
  • Checking the property attribute types on my AppDelegate properties of the UINavigationController and LoginViewController.
  • Retaining a copy of LoginViewController on AppDelegate, though this seems wasteful and didn't make a difference in the outcome.

[EDIT 2]

Question: How is the VC loaded

I have a UINavigationController that is a property on my AppDelegate. That UINavigationController is alloc-init'd in applicationDidFinishLaunchingWithOptions to which I pass my VC as a root view controller. I instantiate the VC at this point.

// Create login/start up views
LoginViewController *loginViewController = [[LoginViewController alloc] initWithNibName:@"LoginViewController" bundle:nil];

self.loginViewNavigationController = [[UINavigationController alloc] initWithRootViewController:loginViewController];

if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad)
    self.loginViewNavigationController.modalPresentationStyle = UIModalPresentationFormSheet;

Note that this is working on iPhone even though I'll present this UINavigationController later as a modal form sheet (not sure if that is contributing to my issue) on iPad.

Some time later in AppDelegate when a different delegate class throws an event I will present this UINavigationController, with my VC in it modally. I do that like this:

if (self.loginViewNavigationController != nil) {

    [self.window.rootViewController presentViewController:self.loginViewNavigationController animated:YES completion:nil];
}

I'm going bonkers trying to determine why this one particular view dragged onto my NIB and wired up the same as all the others is nil on an iPad and not nil on iPhone.

[EDIT 1] While searching for a duplicate question I failed to find this:

A few IBOutlets pointing to nil

I am not alone!

Any ideas?

Community
  • 1
  • 1
Aaron
  • 7,055
  • 2
  • 38
  • 53
  • do you have separate targets for iPhone and iPad? if so is this nib targeted to both? Are you having this problem (not working on iPad) only with this nib? or is it across all nibs? – Nitin Alabur Feb 20 '13 at 22:19
  • No, I'm building a universal binary. The NIB is targeting only one target. I'm only having this problem with this particular NIB. – Aaron Feb 20 '13 at 22:24
  • viewDidUnload is never called. Get rid of it. – matt Feb 20 '13 at 22:38
  • pls show the code that actually causes the nib to load - is it simply the instantiation of some UIViewController? – matt Feb 20 '13 at 22:38

3 Answers3

5

As you are building an Universal app, are you sure you didn't create a separate NIB for iPhone and iPad (LoginViewController.xib and LoginViewController~ipad.xib typically)?

Or maybe you thought you have only one XIB but at some point you had a dedicated XIB for iPad that got compiled into a NIB and even if you deleted the XIB file in your project, the compiled NIB dedicated for iPad is still in the build products.

In any case, try to:

  • Clean your project, or even better, your Build Products Directory
  • To do the latter, you can delete your Derived Data folder ("Organizer" window -> "Projects" tab -> Select your project on the left -> click on the "Delete" button next to "Derived Data")
  • Delete your app from all your Simulators, just to be sure
  • Build and Run again

If this does not work, some ideas to help you debug and identify if the issue is related to the iPad using a different XIB or not:

  • You can try some tests like modifying another IBOutlet of your XIB, for example disconnect one of the other IBOutlet that are not nil from the view it was connected to in the XIB, so that when you run your app again it should be logged as nil this time. If it is nil on the iPhone Simulator (as expected as you just disconnected it)… but still non-nil on the iPad Simulator, then it will definitely mean that you use a different XIB file for iPhone and iPad.
  • You can also change in the XIB the color of our of your UIView that is correctly connected to one of your IBOutlet, and see if the change is reflected in both iPhone and iPad or only on iPhone, so check that this XIB you are editing is the same used in iPad or not.
AliSoftware
  • 32,623
  • 6
  • 82
  • 77
  • Ali - I'll run through your suggestions. To answer your first question, I had a totally separate issue with table cell sizes that I thought I could fix by hooking up a ~ipad.xib. I tried that, it didn't work, then I deleted the ~ipad.xib. I've cleaned the project several times since, to no avail. – Aaron Feb 20 '13 at 22:52
  • Have you also reset the simulator? – Rog Feb 20 '13 at 22:57
  • @Rog - what do you mean by reset the simulator. I'm still relatively new to iOS development so I could be missing something obvious. – Aaron Feb 20 '13 at 23:02
  • @Ali - Steps 1-3 above resolved my issue. I deleted the Build Products Directory, deleted the app from each simulator and voila the ghost .xib issue is resolved. – Aaron Feb 20 '13 at 23:06
  • 1
    Well done. This catches a lot of people, including experienced Xcode users: Building an app does NOT delete stuff in the app from former builds, so you really have no idea what's in there any longer. The only way out is to clean everything. Compare my answer here: http://stackoverflow.com/a/6247073/341994 – matt Feb 20 '13 at 23:51
  • in addition to matt's comment, its important to ensure a clean build is loaded after any nib changes. Most often, changes made in the nib wont show up on the simulator unless cleaned/reset – Nitin Alabur Feb 23 '13 at 03:42
1

I had a similar issue, cleaned my project, deleted Derived Data, made sure I wasn't using separate xibs for iPad; nothing seemed to work. Turns out my issue was super simple. I was init-ing my view controller like so:

// In Swift
let vc = MyViewController()

instead of using the nibName directly:

let vc = MyViewController(nibName: "MyViewController", bundle: NSBundle.mainBundle())

Since my nil-outlet error only seemed to come up when testing on iPad, I never thought to check how the controller was initialized.

WongWray
  • 2,414
  • 1
  • 20
  • 25
0

For this specific case, I faced a weird thing. I had a UITextField become a first-response in viewDidLoad, and I had NSNotifications hooked to that UITextField to manage keyboard frame etc. But interestingly when the notification was dispatched in viewDidLoad, only on iPad, the outlets were nil (unlike iPhone). Weird.

Sean Goudarzi
  • 1,244
  • 1
  • 10
  • 23