42

I saw this used in a WWDC video but only very briefly. They didn't go in to how to create the actual xib file.

I've got a UITableViewCell subclass called MyCustomCell. In this I have several properties UILabels, UIImageViews, etc... all set up as IBOutlets.

Now, in my xib file...

What do I set as the file's owner? Where do I reference my MyCustomCell class is this the file's owner?

Once I've set the file's owner how do I link it with the root view of the xib?

I've tried a few settings but I keep getting errors when using it.

Oh, the code I'm using to register it is...

self.cellNib = [UINib nibWithNibName:@"MyCustomCell" bundle:nil];
[self.tableView registerNib:self.cellNib forCellReuseIdentifier:@"CustomCell"];

Thanks

Fogmeister
  • 76,236
  • 42
  • 207
  • 306
  • Hi, @Fogmeister I have many doubts with, how you are asking the question. Answers are correct as they have correctly understood. In the question title you mention about "register nib", and in the body you ae mentioning about how to link the XIB files with Cell class and out lets. – Arpit B Parekh Nov 11 '16 at 13:13
  • I am sorry, I am in hurry, but my question is do we need to register cell, while we are using the custom cell, with xib. And I a doing the same as your marked answer. I am nt using storyboard. – Arpit B Parekh Nov 11 '16 at 13:15
  • I am out, mostly see tomorrow when I come for job. Thank you. Please. – Arpit B Parekh Nov 11 '16 at 13:34

3 Answers3

48

Normally you don't have to bother about the File's owner in that case, because when the tableView instantiates the cell from the provided/associated UINib along with the reuseIdentifier. It will load all the top-level objects of the nib, and use only the first top-level object that is of class UITableViewCell (or maybe just the first top-level-object regardless of the class? but in general you only have your UITableViewCell in your XIB anyway — without counting the File's Owner and the First Responder which are only "proxies").

In fact, the tableView will try to dequeue a cell and if it doesn't find a reusable one, it will create a new one using the UINib you provided. It will be something similar to this:

NSArray* topLevelObjects = [self.cellNib instantiateWithOwner:nil options:0];
cell = [topLevelObjects objectAtIndex:0];

(That's of course a simplified version just to show the idea, I don't know if it actually calls these exact lines, but it should be quite close)

So the File's Owner is not used in this particular case, and you only need to put a simple custom UITableViewCell as the only top-level-object of your XIB file next to the existing File's Owner anf First Responder (that, again, are only "proxies" / "External Objects references" and won't be instantiated and won't be part of the top-level-objects returned by instantiateWithOwner:options:).


If it still doesn't work:

  • Ensure that you correctly filled the reuseIdentifier of your UITableViewCell in IB (in the Object Inspector pane on the right once you selected your cell in IB), and used the exact same value for this reuseIdentifier property in IB that the one you use in your code.
  • If still no luck, please provide more info, especially what kind of error, log message or exception you have.
mfaani
  • 33,269
  • 19
  • 164
  • 293
AliSoftware
  • 32,623
  • 6
  • 82
  • 77
  • 3
    Thanks! I was leaving the top view as a UIView which is why it wasn't working. Once I deleted that and added a UItableViewCell as the top view it worked fine. Thanks. – Fogmeister Sep 25 '12 at 20:44
  • 3
    I just wanted to comment again. This has been so unbelievably useful! I've refactored a hell of a lot of UI out of my storyboard and in to separate XIB files which has drastically reduced complexity and maintenance of the app I'm working on! Thanks again :D – Fogmeister Nov 30 '12 at 10:45
  • FYI, this is an exception that UIKit throws: "*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'invalid nib registered for identifier (BlahBlahCell) - nib must contain exactly one top level object which must be a UITableViewCell instance" – Pierre Houston Nov 29 '18 at 20:48
11

I've found the code given in the question is fine, but you can't refer to self.tableView in the init method if you're using storyboards. There's some discussion about it in another question.

So the first line goes in the init:

self.cellNib = [UINib nibWithNibName:@"MyCustomCell" bundle:nil];

But this line should go in viewDidLoad or similar:

[self.tableView registerNib:self.cellNib forCellReuseIdentifier:@"CustomCell"];

That fixes my mysterious error, e.g. "*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Could not load NIB in bundle: 'NSBundle <Foo.app> (loaded)' with name 'Ogf-Sj-1ej-view-bBf-Ti-Dda''"

And, yes, I'm doing something very similar to scoop things out of Storyboards and place them in xibs for reuse across view controllers!

Community
  • 1
  • 1
Nuthatch
  • 3,597
  • 4
  • 24
  • 17
  • @fatuhoku Welcome to the world of xcode/objectivec errors. Aren't those crashing breakpoints in the main method so helpful? – csga5000 Jan 07 '16 at 04:48
3

In addition to Answer from "AliSoftware" Note the least obvious thing out here is that the UITableViewCell has to be the Root View *ABOVE* even the UIView. By default when I selected a new IB file it creates a UIView. So deleting the UIView helps. Thanks.

PS: I wanted to comment on that answer but for some strange reason I can't comment, can only answer. Guess I need a certain rating.