IOS/Objective-C: Reusing Cell Throws off Autolayout of Different Size Elements in TableviewCell - ios

I am displaying feed items in a tableview. Depending on the item, the cell must be larger or smaller--for example larger to accomodate a photo or larger still if it references another feed item such as an article and I have to display the item referenced.
In most cases, I've used autolayout to get the cells to auto expand or contract based on the content. However, in a couple cases, this was proving next to impossible so I reset the value of a constraint in code. For example, if there is no photo in one case, I shrink the height of the cell in code as the cell was not shrinking on its own.
This works fine when the page loads. But when you scroll and reuse cells, it leads to weird effects such as the cell expanding vertically or lines being pushed into one another.
Some questions on SO suggest using the method:
-(void) tableView:(UITableView *)tableView didEndDisplayingCell:(IDFeedCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
//Undo changes here
}
The problem is I don't know how to undo changes. For example, if I made a cell smaller by setting
self.height.constant = 100;
Should I set it back to the constant value in storyboard?
What value can I set it to when I don't know what the next item to resuse the cell will need in the way of dimensions.
Thanks for any suggestions. BTW, autolayout shows no issues.

Related

Why do UITableView zero height cells leave space gaps?

My Objective-C Catalyst application has a table view which displays hierarchical data in the form of Groups within Groups and Notes and Groups within Groups. The Groups have a disclosure control that when toggled either "opens" the group to display its contents, or "closes" the group to hide its contents.
The problem, as illustrated by the following two screenshots, is that when a Group containing more than a few items is "closed", a noticeable vertical gap space is shown below the "closed" group. The height of the gap space is proportional to the number of items within the "closed" group. When the "closed" group is toggled "open", the gap space disappears––returns to normal cell spacing. This problem exists in both the iOS and macOS builds of the Catalyst app.
The tableView cells are Style Custom cells. The display of "open" or "closed" groups is controlled by varying the cell height based on whether an item is visible or not. If an item is buried within a "closed" Group, the cell's height is set to zero, otherwise the cell's height is set normally. This is accomplished in the tableView delegate - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
…
…
…
// Node is hidden if an ancestor is collapsed.
if ([model isNodeWithinCollapsedAncestor:node]) {
return 0;
} else {
return [super tableView:tableView heightForRowAtIndexPath:indexPath];
}
}
I have tried numerous modifications in attempt to eliminate these gaps, without success. Among these are:
Varied UITableView attributes.
Varied UITableViewCell attributes.
Set cell.contentView.layoutMargins.
Set cell.contentView.hidden = YES (even worse gaps since it leaves whitespace for every hidden cell).
Varied cell constraints.
Replaced Style Custom cells with Style Basic cells. (Since Basic cells still had gaps, I believe it rules out my Custom cells as the problem.)
Nothing seems to prevent the gap spaces. It appears to me that there is some residual height to a zero height cell, perhaps as little as a few points, but I have had no success in getting rid of the space gaps.

ios dynamic cell height determined by photos and text

I am trying to make a feed very similar to Instagram, everything works however I have ran into a problem I cannot figure out how to solve.
This feed will include photos that are of different sizes, e.g squares, portrait photos and landscape photos.
The problem is I want to resize the UIImageView in the UITableViewCell to match the size of the photo, and also have the UILabel resize depending on how much text there is.
The UIImageView's width will always equal the width of the screen, like Instagram, and only its height will change to make sure the photos are of correct ratio.
Here is a photo of my current cell:
I have tried using autolayout, however I couldn't understand how to get it to work with a UIImageView that will change ratio, from being landscape orientation to portrait orientation etc.
I have also tried in this method here :
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object
Manually trying to calculate the size:
//An example of trying to calculate the size of a view in my cell
cell.cellView.frame = CGRectMake(0, 0, self.view.frame.size.width, 400);
However, it has gotten extremely complicated that way because I don't know how to resize the actual UITableViewCell height to be unique for every cell.
I have also looked at the following resources:
Link 1
Link 2
Link 3
Link 4
Link 5
All of these are tutorials on dynamic cell height, however they do not seem to explain what to do with my situation.
It would be great if anyone could please suggest what I can do to achieve the Instagram style feed with unique cell heights and unique content size within the cells.
As far as I can tell from looking at the app, each item in the feed is actually a whole section in the tableview. The giveaway is the way the username/location/time header 'snaps' into place at the top and everything else scrolls under it. That's a viewForHeaderInSection. Each section then has 2 or more rows: the photo, the toolbar, the hearts/likes info, and then one row per comment.
So instead of making one giant cell and trying to lay everything out inside it, use multiple cells. You can prototype each cell in the storyboard with a unique reuse identifier, then just figure out what kind of cell you're looking at and dequeue the appropriate one from the storyboard.

Resize UITableView to fit all cells

I am using a UITableView within an auto-sized UITableViewCell to display a variable, but small number of items. I want the nested UITableView to expand to display all of its rows. (I know this may not be the best way to do things, so please bear with me on the premise.)
The problem I'm having is that the UITableView does not have an intrinsic size based on the size of all of its cells. Is there any way to force all of the cells to load an then compute an intrinsic size? (Or some other way to have a full-sized nested UITableView.)
Thanks!
There is a method called
- (void)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
where you define the height of each cell. I believe the default is 44. You can just take those values and then multiply them by the number of cells you're populating and that will be the height your UITableView should be.

UITableViewCell size does not follow Content View size

I have two UITableViewControllers which use the same set of cell templates, therefore I have created a table view controller in my Storyboard which contains these templates. My table view controllers instantiate an instance of this template holder tableview, then in -tableView:cellForRowAtIndexPath: they deque one of it's cells, and configure it as they need.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSDictionary *widgetDict = [self.widgets objectAtIndex:indexPath.row];
DMSWidget *widget = [self.widgetStorageTableViewController.tableView dequeueReusableCellWithIdentifier:#"Key Value Row"];
...
return widget;
}
These cells have their inner layouts set up entirely using AutoLayout.
Everything works fine, except that I get cells which have the standard 44 px height and width of the table view, with Content Views narrower than this (depending which they contain, the ones with less contents are smaller), and are longer than the cells themselves. So the Content Views overlap the next cell but don't fill the entire width.
I don't understand, how this could happen. How is it possible, that the UITableViewCell has different size than it's Content View? They should be the same, isn't it?
What I tried to do but failed:
implement -tableView:heightForRowatIndexPath:: tried to return UITableViewAutomaticDimension, but did not help
reload my table view when the sizes are calculated: does nothing
add hacks to cell implementations, like setting autoresizingMask in -awakeFromNib: I could make the Content View expand to the width of the cell itself, but it was still overlapping to the next cell
UPDATE: It looks like it is not related to the dual table view architecture. When I copy my cell to the tableView where it will show up, has the same issues.
I've found the solution: it was all my fault. In some of the ancestors of my cell has an init, which called -initWithFrame: explicitly with CGRectZero. After removing this, iOS 8 could use it's frame values and everything worked fine.

How does UITableView manage cells with variable height

How does UITableView manages cell with variable height? it asks for height of each and every cell/row on load, but moving further how does it "INTERNALLY" ...
Calculate y origin of each and every cell. Calculating one after another is not an issue.
Decide which cell might be lying in a rect given some arbitrary contentOffset. What and how does it maintain its data structure to perform some fast calculation irrespective of number of rows in table view.
How does it manage addition and deletion of rows and update its data structure without much overhead .
Can someone shed light on this... thanks
Basically you need to be careful using cells with variable height, as it can be a performance problem. Your heightForRowAtIndexPath method can be called for cells that are not currently visible, which can be a very large number in tables with a lot of content. Calculating the origins works just like you imagine it would - it needs to know the heights of all cells above the one it's calculating the origin for.
For cells editing you need to add this
- (UITableViewCellEditingStyle) tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewCellEditingStyleDelete;
}
When you perform the deletion operation it removes the content from the datasource array which you are using in the cellForRowAtIndexPath method .

Resources