I have UITableView on UIViewController with content a little bit larger then table's area. When I try to set bounces property to NO, the first tap of the cell stopes to receive after scrolling table to bounds.
I created a test project to receive all nuances of this problem:
1) first selection works fine before scrolling;
2) second selection after scrolling works fine too;
3) there is no problem, if scroll comes to the bounds itself (instead i'll scroll with finger and will end touch after came to the bounds);
4) set bounces property to YES solves problem (bcs scroll can comes to the bounds only itself);
5) highlights of the cell works always;
6) next delegate methods not received (ofcourse only when bug fired)
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
- (NSIndexPath *)tableView:(UITableView *)tableView willDeselectRowAtIndexPath:(NSIndexPath *)indexPath
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
UPD: here's gif with bug, seems that scroll bar not hiding too, when this bug fires
Looks like an Apple's bug of UITableView that needs to report. Here some way to veil the problem (not good, but effective):
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset {
if (!scrollView.bounces) {
targetContentOffset->y = -1;
}
}
Related
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];
}
Today I observed, that my editingAccessory (UITableViewCellAccessoryDetailButton) is too far on the right side, when the my tableView is in editing mode.
When toggling editing on and off I can see the icon move from their regular position to where they are in editing.
In my implementation I'm using
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
return UITableViewCellEditingStyleNone;
}
- (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath {
return NO;
}
EDIT
There is no more code. It's just a plain UITableViewController and the edit button runs noting but the default -setEditing:animated: behind the scenes (as far as I can tell).
EDIT II
Find the complete ViewController implementation here
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)
}
I want to implement a method to be able to reorder the rows of a tableview.
In each section i only have one row. When the editing-state of the tableview is enabled, the move indicators appear as expacted. But when i drag one of the cell to another position, the cell immediatly (after approximatly 1 s) pops back to the original position. This is weired to me, because i implemented such a reorder functionality already. The difference between those two projects are that the new project implements a bunch of gesture recognizers (eg UILongPressGestureRecognizer, UIPanGestureRecognizer, UIPinchGestureRecognizer,..). I already thought about the possibility that one of the gesture recognizers is blocking the drag action of the tableviewcell but its not.
You can see the code below:
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}
- (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath {
//return [NSIndexPath indexPathForRow:0 inSection:3];
return nil;
}
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath {
NSLog(#"%#", destinationIndexPath);
}
Can anyone help me pls?
UPDATE:
I found out that the moved tableviewcell is beeing moved to the original destination index path. Does that indicate, that a reloadData on the table view has happened?
2nd UPDATE:
Because it was menthioned by Andrei Shender why i return nil in the tableView:targetIndexPathForMoveFromRowAtIndexPath:toProposedIndexPath: method you can find my updated code below.
- (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath {
return proposedDestinationIndexPath;
//for testing purpose only
//return nil;
}
Btw when changing my code, i found out, that this method never gets called. Regarding to Apples documents about reordering tableviewcells it should get called.
Thanks to this posting I figured out, what the problem was. Combining a UIPanGestureRecognizer and a UITableView with the reorder/move funcationality is a tricky thing.
When i edit the tableview, i remove the gesture recognizer (of the viewcontroller's view) and when the editing is disabled again, i add the gesture recognizer again.
Be sure to update your data source in the method :
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
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.