I've got a UITableView, each cell has an image and two labels, as you can see on the first picture
So I am trying ti use self-sizing cells and everything is great, except 2 things:
1) First and Second cell don't show content properly, but after I scroll down and then return to them everything is ok. I tried to use [tableview reloadData] in viewDidAppear, but it doesn't help. Watch the labels at first they don't fit. You can watch it on this video https://www.youtube.com/watch?v=I9DGBl1c5vg
Look at the labels on the first cell.
2) It's a tough one. I'm scrolling the table and everything is great, but the problem happens, when I select the row. It's pushing me to detail view, but when I press "back" and return to master view, the tableview jumps,so I'm coming back not to the selected row, also if I scroll the table it doesn't scroll smooth, but jumps. Here are the links for two videos, first one shows that scroll is smooth https://www.youtube.com/watch?v=9wAICcZwfO4 if i don't go to detail view, and the second shows the jumping problem https://www.youtube.com/watch?v=fRcQ3Za1wDM .
It's absolutely sure connected with self sizing cells, because if I don't use it, none of this problem happens.
Okay, I solved both of the problems.
Question 1
I've added these two lines
[cell.contentView setNeedsLayout];
[cell.contentView layoutIfNeeded];
in
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath before return cell
Question 2
The solution appeared to be very simple. I've just needed to implement viewWillDissapear and reload data in it, so the code looks like this
- (void)viewWillDisappear:(BOOL)animated;{
[super viewWillDisappear:animated];
[self.tableView reloadData];
}
Solution for me was simple, if it doesn't work for someone, here I found some useful links.
1) UITableView layout messing up on push segue and return. (iOS 8, Xcode beta 5, Swift)
2) http://useyourloaf.com/blog/2014/08/07/self-sizing-table-view-cells.html
Unfortunately I believe both of the questions that you ask about are IOS bugs.
Question (1)
A easy fix is suggested by this blog.
When the table view is first displayed, you may find some of the cells are not sized properly. But when you scroll the table view, the new cells are displayed with correct row height. To workaround this issue, you can force a reload after the view appears:
Simply add the following to your viewDidAppear method. I have tested it and it works very well.
[self.tableView reloadData];
Question (2)
This second question is a duplicate of this following question:
IOS 8 UITableView self-sizing cells jump/shift visually when a new view controller is pushed
A workaround is suggested by the author of the question himself, which seems okay. However, I have not tried out this one yet.
Okay, I solved it by caching my cell heights in sizeThatFits, and returning that value for estimated cell heights within the delegate. Works beautifully.
Feel free to head over to that question for other proposed solutions.
I would like to implement a UITableView with cells that are full screen. When the user moves the cell up a portion, I would like to jump to the next cell as opposed to allowing it to scroll naturally.
I can't see a great deal of questions or answers out there on this, and perhaps it's because it's a daft idea, but the client wants to see it and the designer has designed it as such so I really must try.
Does anyone have ANY suggestions on how to implement this?
Thanks. (and thanks for pointing out my ignorance in not saying thanks!)
If your cells are going to be the same size as your tableView's height, set the pagingEnabled property to YES. This will make it snap to a full cell on each vertical swipe. I would ensure that the height is exactly full-screen if you do this, otherwise you'll end up with some weird offsets as you scroll.
- (void)viewDidLoad
{
[super viewDidLoad];
// or somewhere similar
self.tableView.pagingEnabled = YES;
}
...
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return self.tableView.frame.size.height;
}
It actually isn't a terrible idea- you could achieve similar functionality with a paging scroll-view, but this has the advantage of not needing to have all of your data loaded at once.
Edit: I also had to make sure to disable automaticallyAdjustsScrollViewInsets on the controller, otherwise I had an undesired initial offset for the first cell, just in case you run in to that as well.
tl;dr: Can I cause the detailTextLabel to have its size updated by the auto layout system in iOS on a value change?
Has anyone else had issues with the detailText label within an UITableViewCell since iOS 8?
I have a table which both text and detail strings. Initially detail text is an empty string (#""). After performing a storyboard segue to an edit screen, I return with a new value for the detail text and update it. I attempt to reload the table in viewWillAppear so that the value is present immediately upon returning to the previous view.
Once the table view is visible again, the table cell has shifted the text field up to make room for the detail text, but no detail text is displayed. The text does not display until I return to the edit screen, and come back a second time.
What I've done to troubleshoot: It looks as thought the auto layout for the detail text label isn't correctly updating as I think it should, and logging the size and makeup of the detailTextLabel's frame confirms this.
I am able to force the text to update by running [table reloadData] within viewDidAppear, however that leaves me with a flicker effect I don't like, and looks unprofessional.
Edit: Additional things I've done: I've also forced the detailTextLabel to re-size itself using [cell.detailTextLabel sizeToFit]. This causes it to display, but offset in an odd way in the cell. After going to the edit page again, the detailTextLabel fixes it's position.
I've created a simple project as a github repo, to show exactly what I'm dealing with:
https://github.com/acidaris/ios8_table_issue
The main code of the view controller I'm using is also below.
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.table reloadData];
}
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section {
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:#"CellIdentifier"];
cell.textLabel.text = #"This is a test";
cell.detailTextLabel.text = self.value;
CGRect frame = cell.detailTextLabel.frame;
NSLog(#"detailTextLabel x=%f y=%f width=%f height=%f",
frame.origin.x,frame.origin.y,frame.size.width,frame.size.height);
return cell;
}
The cell is prototyped within a StoryBoard, and so the cell selected by dequeueReusableCellWithIdentifier: is always defined. Additionally, the cell type within the storyboard is set to subtitle, and it does display if the initial value is defined.
If anyone could help me figure this out, I would be incredibly grateful.
Partial Solution
If you are sub-classing UITableViewCell, you can modify the frame for the detailTextLabel when the layout is done. This is what I've done, and it seems to have worked, but on the 6 plus, I get a weird dividing line between the textLabel and the detailTextLabel. edit: (I have adjusted for this.) I don't like this solution, but thus far it's the best I've come across. It doesn't update after presenting the view, and is relatively simple. As I said above, I will continue to look for a better solution.
- (void)layoutSubviews {
[super layoutSubviews];
CGRect textFrame = self.textLabel.frame;
[self.detailTextLabel sizeToFit];
CGFloat x = textFrame.origin.x;
CGFloat y = textFrame.origin.y + textFrame.size.height;
CGSize detailSize = self.detailTextLabel.frame.size;
CGRect newFrame = CGRectMake(x, y, detailSize.width, detailSize.height);
self.detailTextLabel.frame = newFrame;
}
I've also updated my Github project to reflect my current solution. Edit3: This doesn't work perfectly, as it has wrong values for truly auto layout frames, but it works for my uses for the moment.
Edit 4: I've updated my layoutSubviews function to be smarter. It will size to fix the content within the label, and position the label appropriately within the x/y coordinates in relation to the text label.
Having the same problem. My solution was to call [cell layoutSubviews] before returning the cell at the end of -tableView:cellFForRowAtIndexPath. This works for me, and I didn't find it necessary to override layoutSubviews in the cell subclass.
I have same problem with cell not updating correctly when using segue in storyboard.
Tried
[setNeedsLayout] and [layoutIfNeeded]
on the view and the tableview and it is NOT working.
[self.tableView reloadData] is in viewDidAppear, as it should.
Then I tried the advice from pixbug, and it worked. But one should NOT use [layoutSubviews] directly. So I tried the ones that is adviced by the documents on the cell instead of tableView or the view.
Tried
[cell setNeedsLayout]
but this did NOT work.
Tried
[cell layoutIfNeeded]
this WORKED for me.
I put this before returning the cell.
I had the same problem in an iOS 8 storyboard (without Auto Layout enabled).
I had a Table View with a static Table View Cell at the bottom of it. In IB, I added some spaces into that table cell's content area (Style: "Right Detail"). Then in code (ViewDidLoad), I updated that cell's content with...
self.copyrightsCell.detailTextLabel.text = #"<a string>";
WITHOUT the IB spaces, the cell was INVISIBLE in portrait mode.
But WITH the initial spaces, the cell's content later appears correctly.
Hope this helps someone.
I have the same issue.
I have am certain that the data is available and being assigned to the cell.detailTextLabel.text
I have noticed that once a value has been assigned then there is no flicker if the value is changed on the return to the tableView.
So it appears to me that there is only an issue on the first assignment of a value to the detailTextLabel.
So, I followed this tread and many others. This one lead me to what seems to be the correct answer. I hope this helps others, since this has driven me crazy since iOS 7 / 8 made some sort of changes.
My answer was to put the normal processing code in viewWillAppear and add this [self.tableview layoutSubviews] instead of [self.tableView reload data]. I think this has to do with Apple making things much more controllable in iOS 7 / 8. I struck upon that idea when reviewing some info on how cells were working.
Again, I hope this helps others resolve this annoying problem.
I had a similar problem with a static UITableView. I change a label's text and it doesn't get updated on the screen unless I clicked on the cell or did anything to force update its views.
My workaround was to call after updating the text:
tableView.reloadData()
P.S This doesn't make any sense; because this is a static table view, and I don't know why it worked, but it did!
I think that if you need to reloadData, that means that the table data isn't loaded when its created.
You'd just need to load your data in the viewdidload (or somewhere else BEFORE the table view gets its data ) where your tableview is, and then create the cells accordingly.
Usually, i just use an array of whatever object i'm using and then use [array objectAtIndex:indexpath.row], which you probably know about.
Also, you ante-last paragraph has an unfinished sentence that looks important.
Confirming the problem using Xcode 6.3.2 (6D2105) OS X Yosemite 10.10.3
I made sure that the correct value was being assigned, still first time no show,
second time show.
cell.layoutSubviews() seemed logical to me since it appeared as if the view lacked a refresh and adding layoutSubviews() did the trick.
I have an app that uses a custom UITableViewCell to display detail information after a user clicks on a given row in a table. I can't seem to figure out why the "Reply" button located in the cell is inactive and appears behind the table itself. I can't click on it, select it, or do anything. I used Interface Builder to add the button rather than programmatically add it.
I've tried changing a number of things including the cell's class and File's Owner, but can't seem to get the button to be active and working. I think the button is linked up properly with a connection to a method in the code.
Here's a minimal, complete example of the code:
https://www.dropbox.com/s/atcof58ciqbaojr/CustomCell.zip
Apparently I needed to tell the table view how high the cell was. This is what fixed it:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
{
return 157.0;
}
My iOS app is current transferring control to a detail view when an item in a UITableView is selected. This ia a quiz program, and I'd like to change the app so that it just redisplays the same table view with the correct answer highlighted when a row is selected. What's a good approach for doing this?
Is not clear to me if you know why the detail view is appearing. So I'll explain just in case. If you are giving control to a detail view is because somewhere in your code you are pushing that detail view. It depends on what kind of UITableViewCell you are using. If you are using one of the defaults styles, your detail view is probably been pushed in either:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
or
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
If you are using a custom cell, then you need to look for the method in charge of pushing
that detail view.
I think a good approach would be to:
Remove that pushing wherever it is.
Not to use an `UITableViewCellAccessoryType, if you are using one.
Do something similar to the following on your tableView:didSelectRowAtIndexPath:
Find the row for the right answer in your model array, according to tapped cell.
Use that row number to generate an NSIndexPath.
Use that NSIndexPath to find the correct cell with cellForRowAtIndexPath:
Call setSelected:animated: on that cell to highlight it.
NOTE: If your quiz has more answers than the amount of UITableViewCells that fit in the screen you should scroll your UITableView to the right answer for better UX.