I added the SWRevealViewController to my app, along with the hamburger stack to access my menu. My app has a UITableView for the main application view. I want to allow users to delete items from the list using the swipe to delete function.
I enabled the swipe to delete and added a method call to handle this. I noticed that the method never gets called. Not sure how to get this to work.
Any help would be greatly appreciated.
I was asked for a code example. I have not made any changes to the SWRevealViewController standard source code. In my code for the TableView, I have added the following:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
Normally, the code above should show a delete button when you do a right to left swipe. However, this is not happening. My guess is that the SWRevealViewController is eating the pan gesture recognizer.
Just found a solution after reading a thread of a guy asking a similar question to the maker of this class. Whatever class you use to add the gesture recognizers, make it the delegate of the SWRevealController then paste in this method.
#pragma mark - SWRevealViewControllerDelegate
- (BOOL)revealControllerPanGestureShouldBegin:(SWRevealViewController *)revealController
{
float velocity = [revealController.panGestureRecognizer velocityInView:self.view].x;
if (velocity < 0 && self.revealViewController.frontViewPosition == FrontViewPositionLeft)
return NO;
else
return YES;
}
I have done like this < UIGestureRecognizerDelegate> in .h file in which you are implementing tableview cell delete functionality and in .m file viewDidLoad
[self.view addGestureRecognizer:self.revealViewController.panGestureRecognizer];
self.revealViewController.panGestureRecognizer.delegate = self;
After that simply use this method
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
if ([NSStringFromClass([touch.view class]) isEqualToString:#"UITableViewCellContentView"])
return NO;
else
return YES;
}
Related
I am using XLPagerTabStrip to swipe between pages. One of those pages has a tableview. I am trying to implement swipe to delete on this tableview, but the DELET button only shows from time to time when swiping.
This is the code I have:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
if ([storiesArray count] >= 1) {
// code to delete row
}
}
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"I am allowing a swipe");
// Return YES if you want the specified item to be editable.
return YES;
}
I can see the NSLog I am allowing to swipe so I know the swipe has been detected, but I can only see the DELETE button occasionally. I can't find the reason why it does not show the delete button. I have searched every post on this, and have asked xmartlabs if implementing their code would affect swipe to delete, but it doesn't make sense that it does work occasionally.
Would anyone have any idea what else I can do to understand why the delete button doesn't show ALWAYS?
Thanks.
You can disable scrolling on XLPagerTabStrip's containerView, so the scrolls will be handled by inner views.
There is also a similar question with an answer.
In my application I have a TableView full of cells. Everything works just fine -- When I tap on a cell, it calls tableView:DidSelectRowAtIndexPath: right away and executes a segue, bringing me to the next screen. I also have a search bar, using UISearchDisplayController, allowing users to search through the items in the tableView. When I type some text into the search bar, the cells that match the search display in the table.
Now, my problem is when I tap on one of the cells displayed in this search results table... On one initial tap, the table view does not respond in any way. If the tap is held just briefly, the cell turns gray, as if it were selected, however tableView:DidSelectRowAtIndexPath: is still not called, and the cell turns back to normal after releasing the tap. But if I do a long press for a few seconds, then tableView:DidSelectRowAtIndexPath: is finally called, and I am brought to the correct screen.
Has anyone encountered this problem before? As far as I know I have implemented my UISearchDisplayController the same exact way as I always have, and have never had this problem.
Thank You, and let me know if I can give any additional information that may be helpful
EDIT
I am not certain wherein the problem lies exactly, so I'm not sure which methods to show, but here is some code...
I am bringing up the search bar upon clicking an icon in the UINavigationBar, then removing it from the superview once the editing has finished.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSArray *contentArray;
if (tableView == self.tableView) {
contentArray = self.postArray;
} else if (tableView == self.searchDisplayController.searchResultsTableView) {
contentArray = self.searchResults;
}
// This is pretty hackish, but it wasn't working before for some reason. So I send the PFObject I want as the sender
[self performSegueWithIdentifier:#"ShowPostDetails" sender:contentArray[indexPath.row]];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"PostCell";
PostTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[PostTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
[self updateSubviewsForCell:cell inTableView:tableView atIndexPath:indexPath];
/*
if (tableView == self.searchDisplayController.searchResultsTableView) {
[cell addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(cellTapped:)]];
} */
return cell;
}
#pragma mark - Search Bar Delegate
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"text contains[c] %#", searchText];
self.searchResults = [self.postArray filteredArrayUsingPredicate:resultPredicate];
}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString
scope:[[self.searchDisplayController.searchBar scopeButtonTitles]
objectAtIndex:[self.searchDisplayController.searchBar
selectedScopeButtonIndex]]];
return YES;
}
- (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller
{
[self.view addSubview:self.searchDisplayController.searchBar];
self.searchDisplayController.searchBar.center = CGPointMake(self.view.window.center.x, 42);
}
- (void)searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller
{
[self.searchDisplayController.searchBar removeFromSuperview];
}
I found my problem...
The specific view controller that was experiencing this problem is subclassed from the view controller containing these delegate methods, and contains a UITextField for entering information. I watch for a keyboardDidAppear notification, and when it appears I add a UITapGestureRecognizer to the view to close the keyboard by resigning first responder of the UITextField when the view is tapped. When I added this I had not yet implemented the search feature, so I knew the only reason the keyboard would pop up is for the UITextField. The problem is that this extra TapGestureRecognizer added when the keyboard popped up for the search bar prevented the TapGestureRecognizer built into the UITableView cell from firing. I was looking in the wrong spot for the problem.
To fix the problem I simply made a check that the UITextField is indeed the first responder before adding the gesture recognizer. Now all works as it is supposed to.
So for anyone else experiencing a similar problem, I'd say go back and make sure you don't have any other UIGestureRecognizers that might be conflicting with the gesture recognizers of your tableView.
Thanks to everyone who commented. Helped lead me to where the problem was.
I have UITableView over the full screen. What I would like to know is to find the location where I clicked a cell.
What I want to do is to show the copy option when any cell is clicked.
For that I tried
- (void) touchesEnded:(NSSet *)touches
withEvent:(UIEvent *)event {
//some code
}
but this method is not getting called.
Any idea how can I find user touch over UITableView
if you just want to show Copy option when any cell is clicked then you have to go for
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
method of tableView. there is no need to use Touch event.
Using this method you can get the copy of selected cell using indexPath.
Edit
To get the position of selected cell you can use rectForRowAtIndexPath method
CGRect rectInTableView = [tableView rectForRowAtIndexPath:indexPath];
Edit2
CGRect rectInSuperview = [tableView convertRect:rectInTableView toView:[tableView superview]];
You cannot detect the touch location on a UITableView. For detecting there are two options for you.
1. Either subclass your `UITableView`
OR
2. Add a `UIPanGesture` explicitly in the view.
UITableView inherits the property of pan gesture and UIScrollView by default. Hence by subclassing it you can override the gesture methods and detect UITouchEvents and on the basis of your location you can show the copy option. If you will add a UIPanGesture on your UITableView then you have to add this method in your UIViewController and detect the UIPanGesture touch events.
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}
and your UIPanGesture selector method as below:
-(void) slideView: (UIPanGestureRecognizer *) recognizer {
switch (recognizer.state) {
case UIGestureRecognizerStateBegan:
CGPoint touchLocation =[recognizer locationInView:self.yourTableViewReference];
//Your Rest Of The Code.
break;
case UIGestureRecognizerStateChanged:
break;
case UIGestureRecognizerStateEnded:
break;
default:
break;
}
}
Hope it helps you.
In case of UIScrollview or UITableView, touches methods does not get triggered. Please read more on Responder Chain.
To get the required output you have to sub class UITableView and UITableCellView and override [hitTest:withEvent:] and [pointInside:withEvent:] to get the CGPoint in the respective view.
You can read more here.
Create custom uitableview with hidden copy button and implement the delegate method didSelectRowAtIndexPath and then on the basis of row selection unhide the copy button.
So, I've added a UITableViewController and UITableViewCell into a UIViewController and while the cellForRowAtIndexPath delegate method works, didSelectRowAtIndexPath does not. Does anyone have any ideas?
EDIT 2: The delegate for the UITableView is set to the UIViewController.
EDIT 3: I found the answer to my issue on another Stack question here. Basically I had a UITap... on my [self view] that was blocking the didSelectRow.... I have no idea why the tap blocks the delegate method and I also have no idea how to get both the tap and the table working together simultaneously.
EDIT: The part that bugs me is that I've gotten this exact setup working on an earlier app. So that means I've missed a step somewhere along the way. The thing is, I've combed over all the steps and have compared previous app vs current app and I really have no idea what I missed.
I've added logging to both delegate methods and while one outputs, the other does not.
ViewController.h
#import "...TableViewCell.h"
...
UITableViewDataSource,
UITableViewDelegate
...
ViewController.m
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"cellForRowAtIndexPath");
...
return Cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"didSelectRowAtIndexPath");
}
...TableViewCell.h (contents not important)
...TableViewCell.m (contents not important)
I found the answer on another StackOverflow question.
I had a UITapGestureRecognizer added to [self view] which I commented out, and then the delegate method worked.
Can anyone please tell me why this worked and also how I can get the UITapGestureRecognizer working on the same screen as the UITableView?
// Hide keyboard when user taps outside of it
UITapGestureRecognizer *tapGestureRecognizer =
[[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(hideKeyboardOnTap)];
//[[self view] addGestureRecognizer:tapGestureRecognizer];
EDIT: Corrected typo of UITapeGestureRecognizer to UITapGestureRecognizer
have you set the delegate of the tableView?
myTableView.delegate = self;
EDIT: My bad, did not read that cell for row is being called.
You say that you have used a custom tableViewController. If you have overridden the didSelectRowAtIndexPath method, it might be important to call [super didSelectRowAtIndexPath:] in the tableViewController
EDIT 2: One more thing. I do not know the reason for this, but I faced the same issue some time back in a viewController. I resolved it by adding an empty implementation of didDeselectRowAtIndexPathin the same viewController. Try adding it to your table's delegate controller.
To answer to the question "how I can get the UITapGestureRecognizer working on the same screen as the UITableView";
You should "inform" your GestureRecognizer that other Recognizer can handle the same gesture:
You do that by implementing the method of UIGestureRecognizerDelegate
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
This is a small exemple...
#interface MyController : UIViewController<UIGestureRecognizerDelegate>
{
}
#end
-(void)viewDidLoad
{
UITapGestureRecognizer *gr = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(actionOnTapGesture:)];
[gr setNumberOfTapsRequired:1];
[gr setDelegate:self];
[self.view addGestureRecognizer:gr];
}
-(BOOL) gestureRecognizer:(UIGestureRecognizer *) gestureRecognizer shouldRecognizeSimultaneouslyGestureRecognizer:(UIGestureRecognizer *) otherGestureRecognizer
{
return YES;
}
Check in the interface builder if the property selection is set to 'No selection'.
Change it to 'Single selection' or other option according to your needs.
This might be the reason why didSelect is not getting triggered.
I am creating one table view based application. I have created a custom table cell for table, that contains 2 labels, 1 image and 1 button. The table view Data source method is working properly. I am using xib for both custom cell and view controller class and i connect delegate and data source to the file's owner. But the problem is when i select the table row, didSelectRowAtIndexPath is not getting fire. As mentioned the only way to fire it is to hold down on the cell for about 3-4 seconds. Does anyone have any idea why this is happening?
Thanks for any pointers...
Here is my table view methods..
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [finalAddonsArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
NewCustomCell *cell = (NewCustomCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *nib=[[NSBundle mainBundle]loadNibNamed:#"NewCustomCell" owner:self options:nil];
cell=[nib objectAtIndex:0];
}
Addons *addons1=[[Addons alloc]init];
addons1= [finalAddonsArray objectAtIndex:indexPath.row];
if (addons1.data == nil) {
cell.ivCategory.image = [UIImage imageNamed:#"blogo.jpg"];
}
else
{
cell.ivCategory.image=[UIImage imageWithData:addons1.data];
}
cell.lblTitle.text = addons1.name;
if (addons1.price == nil) {
cell.lblPrice.text = nil;
}
else{
cell.lblPrice.text = [NSString stringWithFormat:#"%# rs",addons1.price];
}
[cell.button addTarget:self
action:#selector(editButtonPressed:)
forControlEvents:UIControlEventTouchUpInside];
cell.button.tag=indexPath.row;
index = indexPath;
cell.selectionStyle = UITableViewCellSelectionStyleGray;
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"sjcjksbcjksbcfkebscf1234567890");
}
One more thing i am getting that if i am using default UITableViewCell instead of custom cell then also my problem is same, delegate method is not getting fire.
Custom cell properties:
same problem happened with me because I have added a tap gesture recogniser over it.
If you have used any gesture recognizer try removing it and check if it causing the problem.
EDIT: Solution as commented by the Ali:
If you have used tap gesture you can use [tap setCancelsTouchesInView:NO];
I was faced with a similar issue:
For me, the problem was because my UITableView was added to an UIScrollView and more specifically to its contentView.
It appears that inside the contentView, I had to stay press 2-3 sec to fire the didSelectRowAtIndexPath method.
I moved my TableView to self.view instead of contentView and it solved the problem!
Maybe you will call the method
[tableView deselectRowAtIndexPath:indexPath animated:NO];
before Push ViewController or Other Operation. Like
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// 1. manual call this method to deSelect Other Cell
[tableView deselectRowAtIndexPath:indexPath animated:NO];
// 2. than do other operation
PushViewController Or Some Animation ....
}
that`s solve my problem .
As others suggested, [tap setCancelsTouchesInView:NO]; does the trick.
However, I want to make one thing clear:
If you think that you did not implement tapgesture and are curious about why you had to add your view into the protected views, check out your class because most probably you have inherited some class and that class includes tap gesture recognizer in it.
In my case, I did the following:
- (NSMutableArray *)tapProtectedViews
{
NSMutableArray *views = [super tapProtectedViews];
[views addObject:self.mTableView];
return views;
}
Edit for Swift 4+
Assuming you have a UITapGestureRecognizer instance named tapGesture:
func disableTapGesture(){
tapGesture.cancelsTouchesInView = false
}
Or you can:
if self.view.gestureRecognizers?.isEmpty == false{
for recognizer in self.view.gestureRecognizers!{
self.view.removeGestureRecognizer(recognizer)
}
}
Dear i faced the same problem. When i tapped the cell but didselectrowatindexpath was not called than it was suddenly called when i released the button after pressing it for few seconds.
If you are facing the same issue there must be a
1. UITapGestureRecognizer that is creating problem for you
or
2. a scroll view in which you placed you table view.
Thus you should remove the gesture or the super scroll view in which your table view is placed
If you have custom gesture object on your view, check override func gestureRecognizerShouldBegin(_ gesture: UIGestureRecognizer) -> Bool delegate. Compare custom gesture with sender gesture, If its not custom gesture object, pass it to the the super. So system gestures/taps won't get blocked.
I'm not sure about this, but Delays Content Touches might have something to do with it.