My apps MainViewController uses a UITableView with custom UITableViewCells from CustomCell. With UIPanGestureRecognizer the user can slide a cell left or right. After the slide, the textLabel.text and slide direction are stored to static NSStrings.
The animation code is CustomCell and works fine.
How could MainViewController know or be notified when CustomCell's recognizer.state == UIGestureRecognizerStateEnded?
CustomCell
static NSString *cellAction = NULL; // textLabel.text
static NSString *slideTo = NULL; // slide direction
-(id)initWithStyle{
UIGestureRecognizer* recognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePan:)];
[self addGestureRecognizer:recognizer];
}
-(void)handlePan:(UIPanGestureRecognizer *)recognizer{
}
MainViewController
-(void)viewDidLoad{
actionTable = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
[self.view addSubview:middleActionTable];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:ident forIndexPath:indexPath];
return cell;
}
After this works I plan on using the 2 static strings from CustomCell to perform a modal segue from MainViewController to AnotherViewController. I only need the 2 strings after the slide action.
add this code
UIGestureRecognizer* recognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePan:)];
[self addGestureRecognizer:recognizer];
right after you create the cell in your MainViewController like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:ident forIndexPath:indexPath];
//more of your existing code here
UIGestureRecognizer* recognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePan:)];
[self addGestureRecognizer:recognizer];
return cell;
}
And move your handlePan: method to the MainViewController.
Unless there's a strong reason for you to have the handlePan: method in the cell class, its best to add have it in the MainViewController (if you want to avoid creating/setting a delegate or using blocks)
Related
In an iOS App, I have a UITableView (NOT part of a UITableViewController) on which I want to detect long press on custom UITableViewCells with the following method:
- (void)viewDidLoad
{
myTableView.delegate=self;
myTableView.dataSource=self;
UILongPressGestureRecognizer *longTap = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(longTapGestureCaptured:)];
longTap.minimumPressDuration=0.5f;
longTap.delegate=self;
[myTableView addGestureRecognizer:longTap];
[super viewDidLoad];
}
-(void)longTapGestureCaptured:(UILongPressGestureRecognizer *)gesture
{
NSLog(#"Long tap"); // never called
}
However the longTapGestureCaptured is never called when I longpress. How can this be resolved ?
I tried your code. it's 100% working for me. But small change in your code is...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//Create cell here
UITableViewCell *cell;
cell= (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
//Add gesture to cell here
UILongPressGestureRecognizer *longTap = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(longTapGestureCaptured:)];
longTap.minimumPressDuration=1.5f;
longTap.delegate=self;
[cell addGestureRecognizer:longTap];
cell.textLabel.text = #"Name";//Send your data here
return cell;
}
-(void)longTapGestureCaptured:(UILongPressGestureRecognizer *)gesture
{
NSLog(#"Long tap"); // never called
}
You add longPress even for UITableview. But when table have cells, cell of table will over on UITableView, so you can not longPress on TableView. Reslove for you is add longPress even on each Cell of Table. By add code add longPress even for each cell in function cellAtIndex. Good luck.
I have a tableview with custom tableView cell present in it.
I have placed a UIImageview on custom tableViewCell. When i press or touch the imageView, i want to download some images from url, on the basis of selected index, which i am going to pass it(selectedIndex) as a string in the url.
What happens is when i first touch the image view, i am not getting the selected index path. But when i first select the cell and then i press the image view, at that time i get the selected index path. I searched it on the internet, but didn't found any appropriate solution. Here below is my code where i assign a UILongPressRecognizer to the UIImageView, in cellForRowAtIndexPath method.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
cell.imgvDownload.tag=indexPath.row;
singleTap = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(tapDetected12)];
[cell.imgvDownload setUserInteractionEnabled:YES];
[singleTap.delegate self];
[singleTap setMinimumPressDuration:0.01f];
[cell.imgvDownload addGestureRecognizer:singleTap];
return cell;
}
The problem is that UIImageview is to able to get the selected index path for the row selected. But if i first select any cell(row) from tableView and then press the UIImage view, i get the index.
Can anyone please tell me what wrong am i doing here. Any help is appreciated.
EDIT
I have slightly changed my code. Instead of using UIImageView and UILongPressGestureRecognizer, i am using a UIButton. And on press of that button i am trying to get the index path of the cell on which the button is present. Here Below is my new code.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
cell.btnDownload.tag=indexPath.row;
return cell;
}
and the button press action method is-
-(IBAction)btnDownload:(id)sender{
UIView *sourceView = [sender view];
if ([sourceView isKindOfClass:[UIButton class]]) {
NSLog(#"row is %ld", sourceView.tag);
}
and on did select method i am storing the selected index path like this-
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
selectedIndex =[NSString stringWithFormat:#"%#%#",[[_shopDArrayFetched objectAtIndex:indexPath.section]valueForKey:#"ctid"],[[_shopDArrayFetched objectAtIndex:indexPath.section]valueForKey:#"scid"]];
NSLog(#"selectedIndex %#",selectedIndex);
}
and i want this index on my button click which i am not able to get.
Also the app is crashing on the line- UIView *sourceView = [sender view]; saying -[UIButton view]: unrecognized selector sent to instance
Any help or suggestions is appreciated.
I noticed you have restore indexPath.row in imageView, so all you need to do is in #selector(tapDetected12) get indexPath.row from imageView. Before you do this, there is one more thing to do: replace you #selector(tapDetected12) with #selector(tapDetected12:) the new parameter is a UIGestureRecognizer instance, from it you can get image view that user long pressed via UIGestureRecognizer's property #property(nullable, nonatomic,readonly) UIView *view.
Sample
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"reuseid" forIndexPath:indexPath];
cell.textLabel.text = self.datas[indexPath.row];
cell.imageView.image = [UIImage imageNamed:#"someicon"];
cell.imageView.tag = indexPath.row;
UILongPressGestureRecognizer *singleTap = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(tapDetected12:)];
[cell.imageView setUserInteractionEnabled:YES];
[singleTap.delegate self];
[singleTap setMinimumPressDuration:0.01f];
[cell.imageView addGestureRecognizer:singleTap];
return cell;
}
- (void)tapDetected12:(UIGestureRecognizer *)gestureRecognizer {
UIView *sourceView = gestureRecognizer.view;
if ([sourceView isKindOfClass:[UIImageView class]]) {
NSLog(#"row is %ld", sourceView.tag);
}
}
Snapshot
You can notice I select row 6 first(label text is 07), when I tap row 3(label text is 04), NSLog output is 3
Try this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// ...
cell.imgvDownload.userInteractionEnabled = YES;
UITapGestureRecognizer *imageTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(imageTap:)];
[imageTapRecognizer setDelegate:self];
[cell.imgvDownload addGestureRecognizer:imageTapRecognizer];
cell.imgvDownload.tag = indexPath.row;
return cell;
}
- (void)imageTap:(UITapGestureRecognizer*)sender
{
UIView *view = sender.view;
NSLog(#"%ld", (long)view.tag); //By tag, you can find out where you had tapped.
}
I have created a custom cell for the UICollectionView. The custom cell has two UIImageView - imageView1 and imageView2.
How should I handle the event for each imageView? I can get handle only the cell event on didSelectedItemIndex delegate of UICollectionView. I want to get handle for each imageView.
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
PhotosViewCell *cell = (PhotosViewCell*)[collectionView cellForItemAtIndexPath:indexPath];
int tag1 = cell.imageView1.tag;
int tag2 = cell.imageview2.tag;
....
}
In your cellForRowAtIndexPath method define tap gesture recognizer with selector and assign it to your image.
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(productImageTap:)];
[cell.imageView1 addGestureRecognizer:tapGesture];
[cell.imageView1 setUserInteractionEnabled:YES];
[cell.imageView2 addGestureRecognizer:tapGesture];
[cell.imageView2 setUserInteractionEnabled:YES];
Then you can do anything you want in productImageTap method. Just get indexPath via locationInView method..
- (void)productImageTap:(UITapGestureRecognizer *)gesture
{
CGPoint point = [gesture locationInView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:point];
PhotosViewCell *cell = (PhotosViewCell *)[collectionView cellForItemAtIndexPath:indexPath];
//do whatever you want with cell properties..
}
I'm a beginner to making iPhone app with Xcode6. (and excuse me non a native English speaker...)
setting up UITableView with customized cells (as another class, i.e. MyCustomCell)
I would like to show/hide a component (UIView) in customized cell class, when a cell in UITableView has a longpress (longTap) but stacked.
I could not know how to control (recognise) the target component on the same cell in customized cell class with indexPath (or something) some part of programs are as follows,
MyCustomCell.h
#interface MyCustomCell : UITableViewCell
#property (weak,nonatomic) IBOutlet UIView *customPanel;
UIViewController.m
#import “MyCustomCell.h"
********************************
- (void)viewDidLoad {
[super viewDidLoad];
[_tableView registerNib:[UINib nibWithNibName:#“MyCustomCell" bundle:nil] forCellReuseIdentifier:#"cell"];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
MyCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
return cell;
}
-(void)longtapAction:(UILongPressGestureRecognizer *)gestureRecognizer {
CGPoint p = [gestureRecognizer locationInView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:p];
if (indexPath == nil){
}else if (gestureRecognizer.state == UIGestureRecognizerStateBegan){
// I would like to change the hidden status of a UIVIEW in the CustomCell like
{self.customcell.custompanel:(indexPath).hidden = YES;}
}
}
Would you please let me know how to go over this trap ?
You need to create and assign a gestureRecognizer in to a cell:cellForRowAtIndexPath
UILongPressGestureRecognizer * recognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(longTapAction:)];
recognizer.delegate = self;
[cell addGestureRecognizer:recognizer];
You can add the gesture-recogniser to the UITableView itself and then extract the target UITableViewCell on which the gesture was performed using something like this or this.
I have a UITableView with custom cell TaskCell. TaskCell has checkboxImageView and I want that when user clicks on the checkboxImageView a method is fired. For some reason it is always firing the didSelectTableView delegate method. Here is my code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"TaskCell";
Task *task = [tasks objectAtIndex:[indexPath row]];
TaskCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[TaskCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
[cell bindTo:task];
return cell;
}
TaskCell.m:
-(void) prepareGestureRecognizers
{
UITapGestureRecognizer *singleTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(onSingleTap:)];
singleTapGestureRecognizer.delegate = self;
singleTapGestureRecognizer.numberOfTapsRequired = 1;
self.checkboxImageView.userInteractionEnabled = YES;
[self.checkboxImageView addGestureRecognizer:singleTapGestureRecognizer];
}
-(void) onSingleTap:(UITapGestureRecognizer *) sender
{
NSLog(#"single tap!");
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
-(void) bindTo:(Task *)task
{
[self prepareGestureRecognizers];
self.titleLabel.text = task.title;
}
If you add the gesture recognizer in your TaskCell.m, then the following line
singleTapGestureRecognizer.delegate = self;
sets the delegate of the recognizer to the cell, not your controller. You should add the recognizer in your controller file so that the delegate is properly set up.
I'm not sure if this will work as I haven't tried myself, but you can try set the recognizer up in your Storyboard and let it be a #property of your cell. Then you can set the delegate to be your controller in your controller file.