UITableView - how to register a cell from secondary view? - ios

If you drag a UITableViewCell onto the top toolbar of a view controller, it appears above the view controller in IB as a secondary view. This is nice because you can do all the layout there. But how do you then get a table view to load the cell from there?
This doesn't work:
[self.tableView registerClass:[MyCustomTableViewCell class] forCellReuseIdentifier:#"MyCell"];
And since it's not in a separate nib file, registerNib doesn't seem appropriate either. Any ideas?

Although that may be possible you have several options when designing tableview cells. You can either design it in a separate .xib file or you can use a prototype cell. Below is an example of a separate .xib file. When you use a separate .xib you would use the registerNib method.
Or with a prototype cell in which the cell is automatically registered with the tableView.

Related

How I can be reusable design custom cells for other view controllers?

I want to design a custom cell for the TableView but want to reuse the same cell for other view Controllers. Before .xib used files, my question is if they are the only option or you can do something like that with the Storyboard.
Yes, You can reuse custom cell for many tableviews creating "CustomCell" class.
To reuse custom cell you have to #import"yourcustomcell" in viewcontroller where ever you want.
Yes.
You can do it and can learn step by step from custom table view cell.

How to reuse the layout of prototype cells in Xcode?

I have two TableViewControllers, and the layout of two prototype cells are the same. Is it possible to extract the layout so that I don't need to maintain multiple copies?
You can move those prototype cells into a xib file and register the UINib on each tableview.
use the cell via xib and you can reuse for the other table
To create xib right click on project on xcode choose new file then choose UserInterface choose view from it and save the name
then for the class of the xib file five your appropriate table view cell class and create outlet of the controls inside table view cell
to load the nib file on table view controller declare these two lines on your table view controller viewdidload function
let nib = UINib(nibName: "your nib file name",bundle: nil)
erxTable.registerNib(nib, forCellReuseIdentifier: "identifiername")
Thanks,

UICollectionView supplementary view in interface builder

For UICollectionViewCell, you can drag&drop a cell in interface builder. Then you can call dequeueReusableCellWithReuseIdentifier in your datasource and everything works just fine.
But how are you supposed to do this with accessory views? I tried drag&dropping a new UICollectionReusableView from the sidebar and I also tried enabling the footer option of the collection view.
In both cases I get the error "could not dequeue a view of kind". Sure you can register the class, but then you have to add all your subviews programmatically.
Or you can use a separate xib file and register that. However I like to keep everything within the collection view instead of having a separate xib file for every view.
You don't have to register the cells, then why should you have to explicitly register the supplementary cells.
What's the trick to do this in interface builder?

UITableView inside UITableViewCell using Interface Buillder

I have an tableView called BasicTable that have custom cell called CustomCell and I want to add a new table view inside this CustomCell.
I have an BasicTableView.m for BasicTable and CustomCell.m for CustomCell and add the new table view using Interface Builder but now don't know where to go or where to add reference to the new tableView and it's new cell.
You can create a reference to the new tableView directly in CustomCell.m (e.g. by setting it as a property) and set the cell itself als dataSource and delegate of the tableView.
Having another tableView inside of a table view cell however doesn't seem like a good design decision, this will lead to problems in UX (e.g. concerning the scrolling of the two). Did you consider using sections inside the table view instead?
Also, if you use my above solution (which I wouldn't recommend because of the UX issues), be sure to update the tableView inside the table view cell, this should best be done in the table view cell's method prepareForReuse, it could look like this:
- (void)prepareForReuse
{
[super prepareForReuse];
[self.tableView reloadData];
}
And do this only after having updated the cell in the table view controller in cellForRowAtIndexPath:
You should connect your new tableview to your CustomCell and set it as datasource and delegate, and implement that protocols in you CustomCell.
i.e. your BasicTable controls by your ViewController, but new tableview controls by CustomCell.

Add UITableView with dynamic content in an XIB file

Is there a way to add a UITableView (not a Table View Controller, but a TableView within another view) and set its content to "Dynamic Prototype" in an XIB file?
This works fine when adding a UITableView in a view controller within the storyboard. However, when I try to do the same in an XIB file, I cannot set its content to "Dynamic Prototype".
Update
In thinking about this recently, there is a fairly straightforward solution to the problem, which is to use the container view pattern.
Basically, add a container view to your xib (or storyboard).
Select the view controller attached by default to the container view.
Delete the selected view controller and drag in a normal uitableviewcontroller onto the IB canvas.
Next, control-drag from the container view to the uitableviewcontroller and select 'Embed' from the available segues types.
Resize the container view to your liking and create the appropriate code file for the table view controller.
Refactor the uitableviewcontroller to a separate storyboard/xib.
Note - The table view controller will be accessible as a child view controller of the view controller that holds the container view in code.
Why is this the correct pattern? 1 Storyboard, 1 Controller. The TableView has it's own controller because it is complex enough to warrant a separate controller. Using the container view pattern allows you to maintain a single responsibility pattern. Avoids controller bloat.
Workaround for original answer
Please be aware of a gotcha where if you resize the tableview; the xml will be regenerated by Xcode and require you to re-add the attribute. I have confirmed that this edit still works in version 9.3+. A sample stub is available at https://github.com/mingsai/test-stub-tableviewdynamic-inxib.git.
Original Answer
Open the file navigator
Right-click on the YourCustomView.xib file
Open As > Source Code
Find the XML beginning with
Within the XML tableview tag locate the style attribute
Leaving an empty space before the style tag, paste in
dataMode="prototypes"
Not 100% sure on this, but I don't think there is a way to set the UITableView content to "Dynamic Prototype" in a XIB file.
However you can achieve the same functionality by creating another XIB file, called something like "MyTableViewCell.xib", that only contains a UITableViewCell, give the cell an identifier, go to File's Owner and in the identity inspector set it to the same view controller class as your table view xib, then create an IBOutlet in your view controller like this:
#property (nonatomic, assign) IBOutlet UITableViewCell *customCell;
then in the XIB, click on the File's Owner and control-drag to the uitableviewcell and set the cell's outlet to the "customCell" property.
(This might be done a lot easier if you find the button that looks like a play button inside a circle in the bottom left hand corner of the graphic editor, click on it, then do your dragging in that column).
After all that, in cellForRowAtIndexPath use code similar to this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"CustomCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:#"MyTableViewCell" owner:self options:nil];
cell = customCell;
}
// Other cell configurations....
}
Hope that makes sense and suits your needs!

Resources