IBOutlet is nil, when NibReusable is prototyped in storyboard instead of registered by code
xiaoxinghu opened this issue · 5 comments
I followed the readme and created MyCell.swift
, MyCell.xib
, changed prototype class and reusable identifier in storyboard to MyCell
. I think I don't need to call register in controller any more, am I right? I tried to register in viewDidLoad
of my controller. It worked, but, the cells don't trigger segues any more. I assume it's been overwritten by the register. What did I do wrong?
Reusable allows you to use methods that are type-safe rather than using String-based APIs. But that doesn't change the way UITableView & UICollectionView work. So if with the normal Apple API you had to register your cells — which you have to, unless your UITableViewCells are designed as prototype cells in the storyboard where your UITableView is, but if your cells are provided by a separate XIB, then register
is still necessary.
So Reusable
still doesn't allow you to skip the call to register
if that call was already necessary before you used Reusable.
The only thing it does is provide you with a single overloaded register
method and determine automatically if that should call register(class: forReuseIdentifier: )
if there's no XIB associated to your cell because you used the Reusable
protocol, or if it should call register(nib: forReuseIdentifier: )
if there's a XIB associated to your cell because you also used the NibLoadable
protocol (or used NibReusable
which is just a typealias for Reusable & NibLoadable
together).
Cells in separate XIBs
- If your cells are in a separate XIB, you have to register your cells, with or without Reusable. That's not new nor specific to Reusable, but to how UITableView works. If you're using Reusable, the advantage you get is you can just using Reusable's
tableView.register(cellType: theCellClass.self)
API which wraps the Apple APIs in a type-safe way. - With cells separated in a dedicated XIB, you can use the same cell and its XIB in multiple tableViews across your application
- But with cell separated in a dedicated XIB instead of directly in the storyboard, you then can't create segues from cells to other screens, because those cells are not prototyped in the storyboard anymore, they are now in a separate XIB and not in the storyboard
Note that all those points are true with or without Reusable. That's explained in the Table View Programming Guide. Using Reusable or not doesn't change those explanations, that's how UITableView have always worked and it's not specific to using my pod or not
Cells in the storyboard, as prototype cells inside your UITableView
If your cells are prototyped directly in the storyboard, inside the TableView they are associated in:
- The storyboard will automatically call register for you, because it knows which cells are prototyped for this tableView so it is able to do the association between the tableView and the cell it's gonna use. So that's a special case where you don't need to call
register
because the storyboard does it for you - But those cells will only be associated with that TableView, and those same cells can't be used with a different TableView elsewhere in your app
- But because your cells will be accessible in your storyboard, you'll be able to use segues to transition to another VC
Again, all those points are true with or without Reusable and are explained in Apple's Programming Guide. That's how UITableViw work, with or without Reusable doesn't change that behavior.
If you want to keep using segues, and don't plan to use those cells in another TableView, simply keep your cells prototyped in your Storyboard instead of creating the MyCell.xib
— so you'll only have your storyboard and your MyCell.swift
file, like what you had before Reusable
— and make your MyCell
class simply conform to Reusable
. Because those cells will be prototyped in your storyboard, you don't need to register them manually, and conforming to Reusable
will allow you to use Reusable's dequeueReusableCell(for: )
method instead of Apple's to dequeue cells in a type-safe way.
All of that is actually explained in the README, so don't hesitate to tell me if that's not clear enough.
1. Declare your cells to conform to Reusable
or NibReusable
- Use the
Reusable
protocol if they don't depend on a NIB (this will useregisterClass(…)
to register the cell)
[…]
final class CustomCell: UITableViewCell, Reusable { /* And that's it! */ }
[…]
- For cells embedded in a Storyboard's tableView, either one of those two protocols will work (as you won't register the cell them manually anyway)
2. Register your cells
Unless you've prototyped your cell in a Storyboard, you'll have to register the cell class or Nib by code.
[…]
Again, thanks for the super detailed explanation.
I think the key point of the confusion for me comes from "prototyped
your cell in a Storyboard". What I did was, in storyboard, creating (dragging) a UITableViewCell onto a table view, change the class to the .xib cell's class, give it the right reusable identifier. I got an empty cell occupying a row in storyboard. I can drag a segue from the empty cell to another view. I consider this is prototyping
the cell in storyboard since it is even labeled Prototype Cells
on the table view (in storyboard).
Yup, that's what I meant with prototyping the cell in the storyboard. But when you do that, the TablView you have in your storyboard will use that cell you dragged on it when you ask it to dequeue a cell. So if you choose that way (using prototype cells in storyboards directly) then you also have to design your cell content in the prototype cells in the storyboard, and can trash your XIB as the TableView won't use your XIBs at all (but the prototype cells in the storyboard instead.
So it's:
- Either use prototype cells in storyboards, by drag & drop a UITableViewCell in your TableView in your storyboard, then design the content of your cells there too, and you'll also be able to use segues from there, but not be able to use the same prototyped cells in a different tableview
- Or don't use prototyped cells in storyboards but use separate XIB, so you'll be able to reuse that XIB for multiple tableViews, but then you'll not be able to use segues and will have to implement the navigation using
tableView:didSelectRowAtIndexPath:
via code instead
But you can't mix "using segues" and "designing cells in separate XIBs".
I strongly recommend you to read the TableView Programming Guides in Apple's documentation. There are also nice tutorials on raywenderlich.com about TableViews and how to use the different options I explained here to create a TableView and its cells with IB. Again, all that is not really related to Reusable per se, it's more general knowledge about UITableView, wether you use Reusable or not doesn't affect all that, it's just the way UITableView and IB work.
Click here for register collectionview cell and display collection custom cell in screen.