I've used Visual Format Language (VFL) to set constraint of the UITableViewCustomCell's subviews.
its working fine when I scrolling my TableView slowly or normal speed.
But its now working when I scrolling TableView fast.
there are 3 different scenario comes.
TitleLabel --> one line text only
DetailTextLabel --> 0, 1 or 2 line only
see this screen shot which is looking correct when I scrolled it slowly
And when I scroll it fast then its not taking correct constraints
And one thing. Log does not displaying any warning. means that all constraints are complete and correct.
I've tried [self updateConstraintsIfNeeded]...etc so many things.
and its working correct when I used Different cell identifier for particular condition. but I don't want to use different-different cell Identifier.
For Autolayout to work correctly it only requires that all constraints are set and that there are no conflicts amongst the constraints. If you fulfill these promises and ensure that your table view rowHeight property is set to UITableViewAutomaticDimension (i.e. self-sizing cells), then everything should work properly. Also, a common mistake is to update the cell data inside of tableView:cellForRowAtIndexPath: instead of tableView:willDisplayCell:forRowAtIndexPath:. As stated in the documentation, the latter method gives the delegate to override state-based properties. Ensure that your table view is using self sizing cells.
Related
I have a UICollectionView with a few different types of cells and am using Auto Layout to use self-sizing cells. To accomplish this, I am setting estimatedItemSize on my UICollectionViewFlowLayout and ensuring the constraints in each of the cells is correct (so I am not using the preferredLayoutAttributesFitting method). The first time the collection view loads, everything looks correct and I get no errors in the logs. Debug View Hierarchy doesn't show any issues either.
In one of the sections, there is a cell that has radio buttons and can cause the height of the content to change based on which radio button is selected. In order to resize the cell after tapping a button, I call collectionView.collectionViewLayout.invalidateLayout().
When this occurs, I get about 3000 lines of logs in the console complaining about broken constraints. It is seemingly complaining about every single constraint present in the cell that was adjusted. However, everything on the screen seems to look exactly how I would want it afterwards, and opening the Debug View Hierarchy doesn't show any issues.
Is this just a product of calling invalidateLayout when Auto Layout is involved? One of the constraints it is complaining about is the the height from the estimatedItemSize, so maybe that is what's causing all of this? Maybe it tries to lay out the view using the estimatedItemSize first and then realizes it should be treated as self-sizing?
Calling reloadData instead seems to work just fine, except it leads to other undesirable behavior and shouldn't need to be used as the underlying data hasn't changed.
I am trying to do something like loading up different type of cells with custom height in a uitableview. The tableview cells are subclassed and consists of labels with the respective constraints. Each cell is having a dynamic height.
Now even before my table reloads the data, I am calculating the height that is required for the resizing of the cells and caching it in my model class so that I dont have to calculate the height when the data is rendered on the device.
To calculate height i did use the tutorial from Ray Wenderlich and I am having the right set of heights applies to the objects.
Now the problem comes. Whenever I am dequeueing the cells there is a
kind of a small jerk that gives me an indication that my cell is
dequeued while scrolling.
How can i make these movement smooth so that there is no jerk while scrolling the view ?
The height is getting assigned in and does get the value as per the current type of data getting loaded.
estimatedRowForIndexPath
Also I am calling layoutIfNeeded from my cellForAtindexPath
Suggestions are most welcome.
It's very hard to say without seeing your code in cellForRowAtIndexPath, and without seeing your cells and their respective code. Here are some general questions I would investigate:
What is the content of the cells and how complex is the view hierarchy in the cell?
Even though you are supplying the correct estimated height, an autolayout pass still needs to happen, and a complex view hierarchy will take time to resolve
Does the cell contain images?
Images that need to be decompressed from a file (UIImage imageNamed:) can be intensive and cause scrolling issues, check images are not bigger than they need to be. If needed, bump this work onto a background thread.
Are you calling a complex method to configure the cell for display in cellForRowAtIndexPath?
Look at the work actually being done in cellForRowAtIndexPath, is there a complex method being triggered in you cell subclass or view model?
Are you adding and removing views to the cell view hierarchy in cellForRowAtIndexPath?
If views are being added, removed, created, inflated from a xib, constrained etc during the cell config, this could slow things down. Try to do only what is strictly needed. Check if there is any code being run internally in the cell subclass during cellForRowAtIndexPath that could be moved to cells initWith... or awakeFromNib methods (ie code that could just run once when the cell is created, rather than every time the cell is displayed)
Also run the Instruments time profiler, see if that offers any more clues
This should be pretty straight forward, but it appears I need to reach out and ask if others have encountered this...
I've got a project on xcode 6 that's targeting iOS 7+. I'm using a storyboard and autolayout. I've created a UIViewController, dropped on a UITableView, and on that UITableView I've dropped on 3 different prototype cells, each with varying height. Each proto cell has its own UITableViewCell class, with UIElement linked accordingly.
These proto cells are designed in the GUI editor of the storyboard, and each of them have a fixed height. The will never grow in height like this: Using Auto Layout in UITableView for dynamic cell layouts & variable row heights
The problem with all examples I keep finding is that they all use a single prototype cell, and vary the height based on the content (i.e. they're using a UITextView and sizing the cell height based on how much text in in the view).
Since my proto cells are already designed in the storyboard, and they will never exceed their design height with dynamic content, all I want to do is show them as they are designed, when they are added to the table.
I'm using a switch statement in the cellForRowAtindexPath to determine which UITableViewCell class to use based on indexPath.row.
I created some dummy data in an array and use it to build a table with 3 rows, to see each of the 3 types of cells being rendered in the table.
This all works perfectly on iOS8. On iOS7, however, all three of my cells visually end up piled on top of each other.
For grins, I then implemented a heightForRowAtIndexPath method, and simply use a switch to determine what indexPath.row I'm dealing with, and then return back the height of the prototype cell (from the dimensions shown in the storyboard designer). This was supposed to be a simple, hard-coded approach to see if heightForRowAtIndexPath was needed to solve the issue.
Again, works great on iOS 8, but on iOS7 all 3 cells are piled on top of each other.
I guess a basic question is: since I'm using storyboard-designed prototype cells, that have fixed sizes and constraints on all of the UIComponent within those proto cells, why doesn't this work on iOS 7?
I'm trying to avoid adding tons of code just make this work on iOS7.
iOS7 doesn't support self-sizing cells, implementing heightForRowAtIndexPath: and returning the correct height is the right way to do it.
Do you calculate height in "tableView:heightForRowAtIndexPath:" ? Maybe you should try to do it in "tableView:estimatedHeightForRowAtIndexPath:", because being dequeue cells copts from storyboard
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.
Context:
Building an app that populates a table that takes in data from a asyc json dump.
The cells are of a custom class (I defined). The main label in the cell can be very long.
It is "placed" in storyboard within a prototype cell but customized via code (pretty standard stuff).
Labels are resized in cellForRowAtIndexPath and rows are resized via heightForRowAtIndexPath -- rows are resized by forcing a call to cellForRowAtIndex like Massimo's answer here
So per the question at hand - I've noticed some interesting (bad) things that happen.
First issue: When the table loads, the rows and labels are dynamically resized correctly! Great! However, when I scroll down and then scroll back up, the label heights will be incorrect -- (for example) the first row was correct at loading. Then when I scroll down and then scroll back up to see it again, it will be truncated. Specifically, the row size will be fine but the label height will change and become truncated to 2 lines only. Wondering if this is because I did both storyboard and coding to customize the cell. Anybody see this before?
Second issue: When I scroll down, while the rows are sized correctly (large), the labels are short (truncated.) Wondering if it's some reverse of the above "potential answer".
"potential answer" is that the rows are all calculated and stored "up front" so that scrolling down/then back up doesn't affect it. However, when cells go "out of view" and are dequeued then when they re-viewed (scroll down/then back up) it will rely on the storyboard.(inappropriately?)
All three of your issues are symptomatic of returning the wrong height in heightForRowAtIndexPath. In my data model classes I have a calculateHeight method that I call in heightForRowAtIndexPath. The model also caches the answer so it doesn't have to recalculate it after the first call. The cell class uses the model's calculated height to layout its subviews.
"ANSWERED" by deleting the prototype cell from the storyboard and making them fully in code, the issue went away. The fundamental workings are still not understood (ie. the interactions between storyboard vs. code when cells are put queued and then viewed again)