how to block didSelectRowAtIndexPath for a subview? - ios

In my tableview, I used custom cell which contains a checkbox. Code to add the checkbox in custom cell class is:
checkbox = [[SSCheckBoxView alloc] initWithFrame:CGRectMake(0, 20, 20, 20)
style:kSSCheckBoxViewStyleGlossy
checked:NO];
[self addSubview:checkbox];
My problem is whenever i click on the checkbox it will call didSelectRowAtIndexPath. how to block this?

You will have to add a UIButton or make the checkbox as a button and then addsubview it in the UITabelViewCell. This will override the didSelectRowAtIndexPath method itself and the button click would make Your action. Also make the Button a bit bigger in size so that the clickable area is justified. Hope this helps.
EDIT :
So if u want to do it i have a way add a bool value IsChecked = YES to the checkbox method. Then when the didSelectRowAtIndexPath method is called , in it add
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if(IsChecked == NO)
{
Ischecked = NO;
// Add your methods
}
}
Hope you got it ....

You can stop selection of by returning nil for the index path. Use the following code.
-(NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath{
return nil;
}

Related

Triggering textfield via Table View did select iOS - Objective C

In an iOS apps I have a table view that has 2 rows with textfield embedded inside.
Textfield2 is a textfield with pickerview input that I set with something like this:
textField2.inputView = pickerView;
So the thing is , the textField 2 icon on the right is only an image embedded in the textfield2.rightview that caused the image to not trigger the pickerView input when tapped.
Did select table view method also wasn't triggered because I set the textfield to fully occupy the cell. Thus, after some searching I find that disabling the textField2 user interaction enabling the didSelect to be triggered.
textField2.userInteractionEnabled = false;
However, now I'm at lost on to how to trigger the input to textField2 pickerView via the didselect tableview method. I tried this line of code but that doesn't work.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"Did select row %d",indexPath.row);
if(indexPath.row == 1){
[textField2 becomeFirstResponder];
}
}
I tried to search how to trigger input manually to textField and didn't find any clue.
Thanks before ! :)
After some debugging with a clear mind, I find that
textField2.userInteractionEnabled = false;
caused the textfield not able be the responder.
So a little workaround with this flag is enable it first in order to edit the text field and disable it again after we finished editing. Something like this :
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"Did select row %d",indexPath.row);
if(indexPath.row == 1){
[textField2.userInteractionEnabled = true;
[textField2 becomeFirstResponder];
}
}
- (void)donePicker {
// to enable the did select row again
[textField2.userInteractionEnabled = true;
}

Display and hide DatePicker on UITableViewCell tap

I have a table view controller in which I need to display a date&time picker when a cell is tapped and hide it when the cell is tapped again. Basically the same effect that the iphone has when you choose your start and end date and time to create a new event in the calendar.
I'm guessing the display and hiding goes in the following method but I'm unsure of what goes inside:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {}
Some example code or link would be great. Thank you!!
Create your cell with whatever you want to show and the picker:
-----------------------------------
cell visible part
-----------------------------------
cell invisible part (with picker)
-----------------------------------
Define a property that let you know if you have to show the entire cell:
#property (nonatomic) BOOL shouldShowPicker;
Initialise this property (on viewDidLoad for example);
self.shouldShowPicker = NO;
A couple of methods to touch:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if(indexPath.row == 4) { //where your picker row is
self.shouldShowPicker = YES;
[self.tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(indexPath.row == 4 && self.shouldShowPicker) { //where your picker row is
return CELL_VISIBLE_PLUS_INVISIBLE_PART;
} else if(indexPath.row == 4 && !self.shouldShowPicker) {
return return CELL_VISIBLE_PART;
} else {
return OTHER_CELLS_HEIGHT;
}
}
You might find my answer here useful which describes what you need to do.
Inline UIPicker Implementation
Essentially you create a custom cell containing a date picker, with optional buttons. You then add this cell below the cell when you edit it and remove it when finished. All explained in the link.

iphone - didSelectRowAtIndexPath: only being called after long press on custom cell

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.

Hiding a Button in a UITableViewCell

I currently have a table with 8 rows that each have a label on the right side and a button on the left. I was hoping that I could have all the buttons hidden until the user presses an "edit" button in the top right corner and then they would appear allowing the user to interact with each table cell. I don't know if this is possible, because they are in UITableViewCells or if there is an easier method to summoning a button for each cell
UPDATE
okay so I have placed in all the hidden properties and there seem to be no errors, but the app doesn't recognize any of it. The buttons remains unhidden despite the fact that they are set to be initially hidden. Here is my code
Here is my Table Cell code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"BlockCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
cell.textLabel.text = #"Free Block";
UIButton*BlockButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
BlockButton.frame = CGRectMake(225.0f, 5.0f, 75.0f, 35.0f);
[BlockButton setTitle:#"Change" forState:UIControlStateNormal];
[BlockButton addTarget:self action:#selector(Switch:) forControlEvents:UIControlEventTouchUpInside];
Blockbutton.backgroundColor = [UIColor colorWithRed:102/255.f
green:0/255.f
blue:51/255.f
alpha:255/255.f];
Blockbutton.hidden = YES;
[cell addSubview:BlockButton];
return cell;
}
and here is my method code:
- (IBAction)Editmode:(UIButton *)sender
{
Blockbutton.hidden = !Blockbutton.hidden;
[self.tableView reloadData];
}
any thoughts or ideas as to what might be the issue?
You'll need to create a UITableViewCell subclass if you don't already have one. In that class, override setEditing:animated: and if the new value is YES, then enable/add/unhide the button.
- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
[super setEditing:editing animated:animated];
if (editing) {
// add your button
someButton.hidden = NO;
} else {
// remove your button
someButton.hidden = YES;
}
}
It would be optional, but you are encouraged to animate the change if animated is YES.
Note: this assumes you have the edit button already hooked up the change the editing mode of the UITableView. If you don't, call setEditing:animated: on the UITableView in the button action. This will automatically call setEditing:animated: on each visible table cell.
The trick here is to keep in mind that a table's cells are determined by cellForRowAtIndexPath:. You can cause that method to be called all over again by sending the table reloadData:.
So, just keep a BOOL instance variable / property. Use the button to toggle that instance variable and to call reloadData:. If, at the time cellForRowAtIndexPath: is called, the instance variable is YES, set the button's hidden to YES; if NO, to NO.
take a BOOL variable which defines the whether to show delete button or not, use this BOOL var to for btnName.hidden = boolVar, initially make boolVar = NO, when user taps on edit toggle bool var and reload the tableview.
Another option is to test if you are in edit mode in the cellForRowAtIndexPath method.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = //(obtain your cell however you like)
UIButton *button = cell.button; //(get button from cell using a property, a tag, etc.)
BOOL isEditing = self.editing //(obtain the state however you like)
button.hidden = !isEditing;
return cell;
}
And whenever you enter editing mode, reload tableView data. This will make the table view ask for the cells again, but in this case the buttons will be set not to hide.
- (void)enterEditingMode {
self.editing = YES;
[self.tableView reloadData];
}

GLTapLabel Inside UITableView

I'm using GLTapLabel to display my text in my UITableView. It will have some links I can click on as GLTapLabels, but when I click those links the tableView:didSelectRowAtIndexPath: fires. So how can I detect the click action in those links?
Implement tableView:willSelectRowAtIndexPath: and return nil for any row you don't want to be selected.
Return Value
An index-path object that confirms or alters the selected row. Return an NSIndexPath object other than indexPath if you want another cell to be selected. Return nil if you don't want the row selected.
For example, to only prevent selection in the first section:
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == 0) {
return nil;
}
return indexPath;
}
You can also try setting exclusiveTouch on the GLTapLabel or overriding its hitTest:withEvent: as described in the answer to Why is UIView exclusiveTouch property not blocking?.

Resources