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?.
Related
I am trying to reduce duplicate code when laying out my tableview but running into lifecycle problems. Basically its that heightFroRowAtIndexPath is called before cellForRowAtIndexPath. Which is what should happen and I understand why.
But...
I have a cell that is laid out in a storyboard. It has an optional field. If the optional field is not in the data then I remove a label for that field. However I am removing that label in a custom cell implementation:
CustomCell (extends UITableViewCell)
- (void) configureCellForData: (Data *) data {
if (data.optional) {
self.optionalLabel.text = [data.optional];
} else {
[self.optionalLabel removeFromSuperview];
}
}
Then in cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:self.tableLayout[indexPath.section][indexPath.row]];
[cell configureCellForData:self.data];
return cell;
}
Which works great for setting up the cell. However the height is wrong if the optional field is removed, ie I need to adjust if the optional field was removed.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:self.tableLayout[indexPath.section][indexPath.row]];
CustomCell *headerCell = (CustomCell *) cell;
if (self.data.optional == nil) {
return cell.bounds.size.height - headerCell.optionalLabel.bounds.size.height;
}
return cell.bounds.size.height;
}
}
It does not seem like much but I simplified my check to "data.optional == nil" and it is more complex than that and involves a DB call.
Is there a better way to set this up such that I don't have to make the check twice once when the height for cell is calculated and once when the cell is initialized?
If you wanted to only check once you could store an array of booleans that stores whether or not the data is there or not. So, make the check for each row, store the result into the array, before you make the check next time, check to see if the array has an value for that cell, if it does, use that value, if not, make the database call.
Make sure that you only store values in the array index associated with the indexPath, and if the array is shorter than the indexPath you're at, you know you need to make the call and add the value into the array.
Edit: As I think more about it, I would put the bool value on the cell itself, and then just call cell.isDataAvailable (or whatever you want the value to be) in order to avoid the second call when you go to set the cell up, as you would have already checked this in heightForRowAtIndexPath.
When i tap one of UICollectionView's cell more than once-double tap, triple tap-, it's delegate method didSelectItemAtIndexPath also get called more than once. What can be the slickest way to prevent it?
I would appreciate any comments.
You can use your model object to hold selected property in it (or you can create a boolean array for only this purpose) . And check it in shouldSelectItemAtIndexPath method.
#cihangirs code:
- (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath {
if (someModel.isSelected) {
return NO;
} else {
someModel.isSelected = YES;
return YES;
}
}
This is safest way to do your objective:-
(void)collectionView:(UICollectionView *)collectionView
didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
if([[collectionView indexPathsForSelectedItems] containsObject:indexPath]) // checking whether cell is already selected or not
{
return;
}
else
{
// do whatever you want to do on selection of cell
}
}
The thing happening here is, whenever you select a cell it automatically get stored "indexPathsForSelectedItems" of Collection view, so the next time you tap on the selected cell again this method [[collectionView indexPathsForSelectedItems] containsObject:indexPath] will check whether that cell is already selected or not , if yes then it will return the method so that it doesnot go any step further.
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.
Here are tableView data source and delegate implementation, and I set the maximum selection is 5.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
...
if ([multiOptions count] > 5) {
[self tableView:tableView didDeselectRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryNone;
cell.selected = NO;
//show alert
}
...
}
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
...
[multiOptions removeObject:selectedOption];
...
}
but here comes a question, if the options exceed the limit, the first click on cell will work just fine. but second time click the cell will call
didDeselectRowAtIndexPath
again, that's not what i expected, and I tried
[tableView deselectRowAtIndexPath:indexPath animated:YES];
in didSelectRowAtIndexPath, it didn't work, can someone give me a hint, how to correct it? thanks.
You have to check this in tableView:willSelectRowAtIndexPath:
Have a look at the UITableView class reference
especially at the last sentence:
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.
So something like this will work within tableView:willSelectRowAtIndexPath::
if ([multiOptions count] > 5) return nil;
i have custom tableviewcell which has a textfield inside for user input text, now how can i find cursor is in which cell?
tableview willBeginEditingRowAtIndexPath and tableview willSelectRowAtIndexPath does not return the correct index.
in editingStyleForRowAtIndexPath i want to retun UITableViewCellEditingStyleDelete just for cell that cursor is inside. how can i do that??
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(self.uiTableView.editing)
{
return UITableViewCellEditingStyleDelete;
}
else
return UITableViewCellEditingStyleNone;
}
So thanks inadvance
in the customecell, put id that carry the index , and in creation of table when create the cell set this id with the value
http://adeem.me/blog/2009/05/30/iphone-sdk-tutorial-part-6-creating-custom-uitableviewcell-using-interface-builder-uitableview/