cellForRowAtIndexPath not call during device rotation - ios

I have a UITableView with some delegate methods.During load for the first time it's all ok, but during the rotation I saw that the method cellForRowAtIndexPath doesn't recall. Why?
My delegate method are:
-(NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section{
//.....
}
-(CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
//......
}
- (UITableViewCell *)tableView:(UITableView *)aTableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath{
//...This method is not called during the rotation of the device...
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
//.......
}

You need to refresh table data manually after the rotation occurs using [tableView reloadData] within shouldAutorotateToInterfaceOrientation method.

That method is only called when the cell is about to become visible on the screen and the table requests it. Once it is in the view, it will not be called again until it has scrolled out of view and then back.
You have 3 options for handling the rotation:
Use AutoLayout
Use Springs & Struts
Override layoutSubviews (which will get called on a rotation)
What you choose will depend on how complex your cell layout is. Also, make sure the table resizes on the rotation, otherwise the cells won't see a size change.

Related

iOS11 Drag behavior not working in UITableView

I am facing a problem while developing Drag&Drop iOS11 feature to allow send and receive data between apps.
In the tableView of a view controller, with it's dragDelegate and dropDelegate assigned on viewDidLoad to the view controller itself, I implement the
- (NSArray<UIDragItem *> *)tableView:(UITableView *)tableView itemsForBeginningDragSession:(id<UIDragSession>)session atIndexPath:(NSIndexPath *)indexPath method, but it is never being called.
The drop behavior is working correctly and the table view can consume items from other apps such Photos or Notes. But when I tap a table view row for a couple of seconds, nothing happens. The lift animation doesn't occur and the drag delegate isn't fired.
Any thoughts? Am I missing anything required?
On iPhone, besides setting the dragDelegate you must also set dragInteractionEnabled on the UITableView to true. On iPad, this property is set to true by default.
Please try below delegate methods for re-ordering of cell.
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewCellEditingStyleNone;
}
Implement the following UITableView datasource method in your project.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
{
[dataArray exchangeObjectAtIndex:sourceIndexPath.row withObjectAtIndex:destinationIndexPath.row];
[self.tableView reloadData];
}

Row selection doesn't work on first tap after scroll in a non-bouncing UITableView

Basically the problem I'm seeing seems like an Apple bug. The problem is after scrolling the table, the first tap on any row only highlights it. A second tap is needed to actually select or deselect it. I noticed that this problem happens most of the time. Very few times it will work as expected, but I haven't noticed any pattern as to when it works.
This issue only happens if theTableView.bounces = NO; otherwise, it works perfectly.
I verified this by implementing the appropriate delegate methods.
First tap on any row after scrolling, I get these call backs
-(BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath
-(void)tableView:(UITableView *)tableView didHighlightRowAtIndexPath:(NSIndexPath *)indexPath
-(void)tableView:(UITableView *)tableView didUnhighlightRowAtIndexPath:(NSIndexPath *)indexPath
Subsequent taps on the same or a different row after scrolling, I get these call backs
-(BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath
-(void)tableView:(UITableView *)tableView didHighlightRowAtIndexPath:(NSIndexPath *)indexPath
-(void)tableView:(UITableView *)tableView didUnhighlightRowAtIndexPath:(NSIndexPath *)indexPath
//then
-(NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
//or
-(NSIndexPath *)tableView:(UITableView *)tableView willDeselectRowAtIndexPath:(NSIndexPath *)indexPath
-(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
I have seen other similar questions, but all of them are using a table inside another scroll view, which isn't the case here.
Has anyone found a fix or a workaround for this? I tried on iOS 7.0 ... 8.2 and the problem is present on all of them.
Thanks!
After a lot more testing, I found that the problem happens when the table's contentOffset.y reaches maximum value or 0. So I created my own "bouncing effect" but on a much smaller scale by implementing scrollViewWillEndDragging:withVelocity:targetContentOffset: in the table view's delegate as follows:
-(void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
{
targetContentOffset->y = MAX(targetContentOffset->y -1, 1);
}
With that in place, the problem disappeared. It's a workaround but works like a charm!
Swift 4 syntax of this comment:
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
targetContentOffset.pointee.y = max(targetContentOffset.pointee.y - 1, 1)
}

How to find out if a UITableViewCell has scrolled away and is invisible

I have a UITableViewCell that observes (via KVO) some properties. This only makes sense if the cell is visible. I want to remove this observer when the cell scrolls away, and before prepareForReuse is called.
How can I do this?
Your table view delegate can implement
- (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
and in there you can call a method on the cell to perform the cleanup you want.

UITableView not detecting the the accurate tapped row

I have just added a UITableView in to my storyboard and the suggested constraints to it like that.. Now i have written very simple code with some delegate and datasource methods implemented like this. . Now when i tap the first row it detects nothing and check the console in the below image, when i press the second row it tells me that the indexPath.row is 0.. can some body point out that what i am doing wrong here.
You are calling -(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath which is called when you deselect row , instead call
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
It's because you are using didDeSelectRowAtIndexPath: instead of didSelectRowAtIndexPath: method.
You have to call "didSelectRowAtIndexPath" Delegate method.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
This method only return which row we have selected.

Compare Reuse Identifier Crashing

I need to have a custom cell height for all of my cells in my UITableView. In this method:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
I try this:
if ([[tableView cellForRowAtIndexPath:indexPath] reuseIdentifier] == #"imageCell")
As I have 3 different cells setup with different identifiers in my storyboard. However my app just crashes here with EXC_BAD_ACCESS.
Any idea why?
Thanks.
You're comparing a string, so you should be using isEqualToString:
if ([[[tableView cellForRowAtIndexPath:indexPath] reuseIdentifier] isEqualToString:#"imageCell"])
(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
you are supposed to calculate the height for you row, not to get the Cell of your tableView.
In my opinion, in the lifeCycle of a TableView delegate, the 1st step (before allocating each UITableViewCell), the TableView delegate call heightForRowAtIndexPath for each row (but at this moment, the UItableViewCell are not allocated). The, in a 2nd step, the TableView call
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
to create UitableView Cells.

Resources