autolayout constraints in nib not honored for UITableViewHeaderFooterView - ios

I have a UITableView with several columns of data. The reusable cells are loaded from an xib file which has the appropriate labels and autolayout constraints. Everything works perfectly; the table columns are laid out correctly on different devices and when the devices are rotated.
The problem I am having is trying to create a table footer to show the totals of the columns in the table.
I created an xib file with the same autolayout constraints as the cell xib file and am loading it in tableView.viewForFooterInSection the same way I did for the cells. As required, I am using a subclass of UITableViewHeaderFooterView instead of UITableViewCell.
The awakeFromNib method in the UITableViewHeaderFooterView subclass sets the background color, so I can see that it is the correct size on all devices/orientation, but the labels from the footer xib file are not getting laid out to match the table cells.
The autolayout constraints from the footer xib file are not being honored. When I set a different background color in the footer xib file, the table footer shows this background color for the length of the xib's view.
I'm new to all of this technology and would greatly appreciate help in resolving this incredibly frustrating issue.
Is there a way to use autolayout for UITableViewHeaderFooterViews loaded from nibs?

You should call setNeedsUpdateConstraints() to update your view.
From apple documentation
Controls whether the view’s constraints need updating.
When a property of your custom view changes in a way that would impact constraints, you can call this method to indicate that the
constraints need to be updated at some point in the future. The system
will then call updateConstraints as part of its normal layout pass.
Updating constraints all at once just before they are needed ensures
that you don’t needlessly recalculate constraints when multiple
changes are made to your view in between layout passes.
Also, you can update view throw layoutSubviews()
Lays out subviews. The default implementation of this method does
nothing on iOS 5.1 and earlier. Otherwise, the default implementation
uses any constraints you have set to determine the size and position
of any subviews. Subclasses can override this method as needed to
perform more precise layout of their subviews. You should override
this method only if the autoresizing and constraint-based behaviors of
the subviews do not offer the behavior you want. You can use your
implementation to set the frame rectangles of your subviews directly.
You should not call this method directly. If you want to force a
layout update, call the setNeedsLayout method instead to do so prior
to the next drawing update. If you want to update the layout of your
views immediately, call the layoutIfNeeded method.

Related

How can I use a xib with auto layout in iCarousel?

I have an iCarousel set up to reuse a certain xib. This xib is using AutoLayout (as I am in the rest of my project). Apparently iCarousel does not use AutoLayout, and it does not work correctly with it. The view's constraints appear to be calculated for another frame, and then the view seems to resize...
I have an example project showing my setup here
Here are some images of my troubles:
The first view is correct:
The second and all the others screw up in another way:

UITableView Visible Cells Not Laying Out Subviews When View Appears

I have a UITableView that has multiple sections, with custom UITableViewCell subclasses populating the table. Within these UITableViewCell subclasses, I am implementing layoutSubviews to customize the position of labels, etc.
All of the cell's subviews are adjusting as they should, except the first batch of visible cells upon the view loading. They are identical to how they are laid out in storyboard, which is not what I want. For example:
http://i.stack.imgur.com/L5GJh.png
Note: The green and orange borders are a visual aid to see if the labels are resizing.
Upon scrolling, all of the new cells that appear have their subviews the way that I programmed them to be in layoutSubviews. As far as the first batch of visible cells, I can scroll them offscreen and then back on, and then the subviews are laid out perfectly. For example:
http://i.stack.imgur.com/jgjch.png
Within tableView: cellForRowAtIndexPath:, I call [cell layoutIfNeeded] before the method returns the cell. If I change this to [cell layoutSubviews], then the inverse happens, where the first batch of visible cells are laid out as they should be, but all of the cells that get loaded upon scrolling are not laid out properly.
I have tried to put [cell layoutIfNeeded] within [tableview: willDisplayCell: with no luck. Any ideas on how to fix this?
Thanks in advance!
This is the behavior you'd see if you were setting frames in your layout code with Auto Layout enabled. This won't work. The Auto Layout system is responsible for setting frames and will overwrite the values you set.
You should either specify your layout using constraints or turn off Auto Layout.

Custom UITableViewCell's subviews using auto layout - no xibs, all in code

Custom UITableViewCell's subviews added in code using auto layout works (verified). However the whole point of doing this was to not have to calculate the height of each tableview cell and the delegate method heightForRowAtIndexPath expects a height while drawing the tableview.
How can I figure out this height based on content using the auto-layout (visual format language based addition in code already added and working) and return it to this heightForRowAtIndexPath?
Also I'm I can't really do this on a background thread (or can I?) and therefore if I have a UITableView using this backed by a list of say 1000 records, this will take forever, is that right?
Autolayout in this case just means that you don't need to calculate the frame sizes of your subviews within each cell. It's got nothing to do with the heightForRowAtIndexPath method - this is used by the table view to define the cell's frame, which will then inform the layout of the subviews.
Using Autolayout to determine the heights would likely be pretty slow, and you can't do it on a background thread. If you have 1000 rows then I'd consider a hierarchical structure instead of a single table as that will be pretty tedious to scroll through. You could also consider calculating the heights at the point of setting or creating the data.
You may be able to set up an offscreen view using your constraints, populate it with your data for each item, then record and cache the height. However you'd have to do this at the data end rather than in the height method, as it would be far too slow.

How do I get the size for a UICollectionView cell when layoutSubviews hasn't been called

I'm trying to create a UICollectionView where the cells are varied sizes based on the contents within them and how those contents play with the constraints set on them. Basically, I need to examine the frame size but this size isn't updated on the cell until after the subviews have been laid out. Unfortunately, this isn't done until the view is attached to the window hierarchy it seems. I can't find any series of calls to trigger this without adding it to the window hierarchy, yet I don't want to add it to the hierarchy except through this UICollectionView. And, of course, the collection view wants the size of it before it requests and adds the cell.
I can't get to size without adding it to the window hierarchy (I think), and I can't get it added to the window hierarchy (i.e. the collection view) without having the size. What am I missing here?
Just call these on the cell, and it should act as though it was added to the view hierarchy:
setNeedsLayout()
layoutIfNeeded()

Getting real width of UITableViewCell's contentView before it displays

I have a grouped table view with custom cells (created programmatically by subclassing, not with IB). To properly position custom cell's subviews (such as labels and text fields), I need to know the current width of the cell's contentView just before the cell displays (taking into account that real cell width in a table view can change (according to screen orientation, modal presentation style, etc.)).
if I override in custom cell class the layoutSubviews method, it works perfectly, but it can be called frequently, thus I have to reposition my subviews every time when it's called, even when there's no need to do that.
Please, recommend me more elegant solution.
The recommended way of doing this is by setting the autoresizingMask of the table cell. If you need to have more control over the layout, you can store the last used view width in a member variable, and only layout the subviews if this differs from the current view width.

Resources