Different elements for specific UITableViewCell - ios

Recently I am using twitter official iphone app. I noticed their UITableViewCells have some elements like label, image view and button. But not all of the cells have the same elements, some cells have a someone retweet label, but some cells don't. and some cell have images and some cell don't. So the question how they do it? Are they using multiple dynamic prototype cell?

You can create multiple cells in your story board and assign them different identifier.
Now you can dequeue different cell base on your logic
if(SomeConditionIsSatisfied)
{
cell = [tableView dequeueReusableCellWithIdentifier:#"cell1"];
}
else
{
cell = [tableView dequeueReusableCellWithIdentifier:#"cell2"];
}

There are multiple approach to achieve this.
Use different prototype cell.
Use same cell and manager your UI in cellForRowAtIndexPath. As in write conditions and tweek your UI accordingly.
Best we to do it is using a different prototype cell.

Related

Reusing cells with dynamic layout content at runtime

I have a type of UITableViewCell that lets the user add/remove as many UITextViews as they want at run time.
I'm running into issues when trying to reuse/dequeue cells of that type, as sometimes the tableview cells just start overlapping when you scroll up and down. When I dequeue/return the cell, I'm running a setup method (which initiates a teardown method internally first to remove all the previous views), and uses the model to setup/restore all the necessary views and layout constraints.
if let cell = tableView.dequeueReusableCell(withIdentifier: "MultipleContentCell", for: indexPath) as? MultipleChoiceTableViewCell {
cell.setupCellWithModel(model: model)
cell.setNeedsUpdateConstraints()
cell.updateConstraintsIfNeeded()
cell.delegate = self
return cell
}
I can't really figure out why that cells sometimes overlap in the tableview, but I'm guessing it has to do with the layout being recreated on the fly. I'm considering not reusing these types of cells and just storing them in a list.
My question is: are reusable cells always suppose to have the same general UIView layout, and only the content changes? Am I not supposed to use reuse these types of cells? Or has someone experienced this before?
Thanks
The UITextView are created each time you dequeue cell and never delete. To repair that use function prepareForReuse(). You have to define, what your cell should do before dequeue in MultipleChoiceTableViewCell. For example:
override func prepareForReuse() {
super.prepareForReuse()
for view in speciesName.subviews {
if view is UITableView {
view.removeFromSuperview()
}
}
}
I added similar question few days ago:
Cells in UITableView overlapping. Many cells in one place
If you have some question, I can try to help you more tomorrow.
Cheers!
In general, yes. You want the physical layout of your cells to be static, and only vary the contents when you recycle them. If you add views to your cells in cellForRow(at:) then the burden is on you to manage the extra fields to avoid duplicate views.
Your case where you add a variable number of views to a table view cell based on user interaction is an odd case where you might need to add and remove cells on the fly.
One way to handle this would be to put all of your text fields in a container view, add an outlet to that container view, and then simply use code like this in your prepareForReuse or cellForRowAt function:
containerView.subviews.forEach { $0.removeFromSuperview() }

Is there a way to access the cell that is shown the most in a CollectionView in Swift?

I am trying to modify the design of my UICollectionView based on the cell that is seen at any given time. Meaning that if I have a first cell, and then half of another one, I'd like to access and modify the one that the user is likely focusing on, which is the complete one.
Is there a way to do this in Swift?
Please see attachment (In this case, I'd like to programmatically change the cell that says Pirkei Avot):
for ( UICollectionViewCell *cell in theCollectionView.visibleCells) {
CGRect rect = CGRectIntersection(theCollectionView.frame, cell.frame);
//check width of each cell
}

How do I do the UISearchDisplayController's tableView to use the prototype cell defined for the regular tableView

I have a tableViewController with a search bar and a search display controller.
That main tableViewController's tableView has a prototype cell defined on storyboard.
I am having crashes on the line
FileManagerTableViewCell *cell = (FileManagerTableViewCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
when the search tableview is about to be displayed. Apparently the search tableView cannot access the prototype cells defined on the main tableView on storyboard.
How do I make the search tableview access the prototype cell defined for the main tableview on storyboard?
If you want both tables to use the same cell, you should design that cell in a xib file instead of in the storyboard. Have both tables register the nib, using
registerNib:forCellReuseIdentifier:.
The answer to this is simple to edit but complex to understand why Apple created something half-cooked like that. The solution comes from the first comment of this answer
The answer is to use self.tableview instead of tableview.
FileManagerTableViewCell *cell = (FileManagerTableViewCell *)[self.tableView dequeueReusableCellWithIdentifier:cellIdentifier];
The explanation: when a search starts, iOS switches to show the search tableview but that tableView has no prototype cells, so this line
FileManagerTableViewCell *cell = (FileManagerTableViewCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
is asking iOS to dequeue a cell from the search tableView. By using self.tableview, you are saying to dequeue a cell from the main tableView, that contains a prototype cell defined on storyboard.
I hope one day iOS APIs are designed to make our lives easy, thing that is far from happening today.

How to reuse custom UITableViewCell defined as a prototyped cell in Storyboard controller

I have the only cell template for items at two different UITableViewControllers/TableViews.
What I need is to define it once and then reuse at other UITableView via
UITableView.DequeueReusableCell(CellId);
The issue is that is when I call this method on UITableView which doesn't contain cell prototype I'm getting NULL.
How to reuse my prototyped cell across multiple table controllers?
I want to define cell template in storyboard, NOT xib.
It turned out that the only way to reuse a cell it to design it with xib and register at tableview that xib with cellid.
Just copy-paste your prototype cell in every table view controller where you need it.
And if I understand your question, in a standard and proper way, it's not possible to dequeue a cell from another table view, Apple implementation handles this mechanism itself.
Using xib for a reusable cell is beneficial while cell design is fixed in the whole app. But when there are conditional requirements or slight changes in design or functionality and remaining design and functionality is same for tableview cell, in this case if you still want to reuse the code then you can subclass tableview cell class.

Adding rows to UITableView built from Storyboard

I have a static UITableView built from a Storyboard that works well. I want to fill the first category programmatically, though, from a user-defined file
Simply put, I want to go through all the strings in an array and add them as cells for the rows of the first category. For the second category, I have a series of mildly complex cells (containing a number of labels, textfields, buttons and other controls), defined in the storyboard, that I don't feel like recreating in code.
As far as I understand, the default behaviour for a UITableView built from a storyboard is to use the nib file as an implicit datasource. If I use a custom class as datasource, my second section doesn't work. I have thought of two possible ways to fix this:
Fill my first category from the datasource and delegate the rest to the nib file. Is this possible? Is there some method to programmatically ask the nib to fill my UITableView?
Export my storyboard-built cells into code and paste this code into my datasource. This method has the disadvantage of making my second category harder to modify.
Is one of those two options feasible? Is there another option?
I would use dynamic prototype cells. Then, I would set up the ViewController as the delegate and the dataSource. I would then create a custom subclass of UITableViewCell and connect the elements of the second section to IBOutlets in the custom UITableViewCell.
If the first section wasn't something that could be done with one of the generic cell types, I would also create a custom subclass of UITableViewCell for that section as well.
I would then use the cellForRowAtIndexPath: method to set up the cells with the information that I want in them. So if my first section used FirstSectionCell and my second section used SecondSectionCell as custom subclasses of UITableViewCell my cellForRowAtIndexPath: would look like this:
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(indexPath.section==0)
{
FirstSectionCell *firstCell = [tableView dequeueReusableCellWithIdentifier:#"First Cell Prototype"];
//Set up the first cell.
return firstCell;
}
else if(indexPath.section ==1)
{
SecondSectionCell *secondCell = [tableView dequeueReusableCellWithIdentifier:#"Second Cell Ptototype"];
//Set up second cell.
secondCell.someLabel.text = #"whatever";
//etc.
return secondCell;
}
else
{
//if you have another section handle it here.
}
}
There are two kinds of table views when you use Storyboards:
Static
Dynamic
You're currently using the former. You define everything in the Storyboard and have very little code.
But you need to change to the latter.
You can still keep your UITableViewCells in the Storyboard; there's no need to do that in code (though you can if it makes things easier). You can refer to the template cells using the "reuse identifer."
Otherwise you've pretty much got it. You'll need to write code to implement the data source and (possibly) more methods of the table view delegate.
It's kind of fiddly switching from static to dynamic. I keep meaning to raise a Radar because I'm sure Xcode could be making it easier to do...

Resources