NSIndexPath return nil
Try sending a delegate to the nextviewcontroller like
DestinationViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:@"DestinationViewController"];
controller.args=myArgs;
controller.delegate = self;
[self.navigationController pushViewController:controller animated:YES];
and when traversing back from that viewController to the present table viewcontroller pass that delegate.
This may help you...
tableView:indexPathForCell returns nil
It could be that the cell is not visible at this moment. tableView:indexPathForCell returns nil in this situation. I solved this using indexPathForRowAtPoint this method works even if the cell is not visible. The code:
UITableViewCell *cell = textField.superview.superview;
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:cell.center];
iOS - indexPathForRowAtPoint don't return correct indexPath with different cell height
One way to do it would be to add a UILongPressGestureRecognizer to each UITableViewCell (that all use the same selector), then when the selector is called you can get the cell via sender.view. Perhaps not the most memory efficient, but if the single gesture recognizer won't return the right row in certain situations, this way should work.
Something like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
...
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]
initWithTarget:self action:@selector(handleLongPress:)];
[longPress setMinimumPressDuration:2.0];
[cell addGestureRecognizer:longPress];
[longPress release];
return cell;
}
then
- (void)handleLongPress:(UILongPressGestureRecognizer*)sender {
UITableViewCell *selectedCell = sender.view;
}
indexPathForCell returns nil since ios7
Your approach to find the "enclosing" table view cell of a text field is fragile,
because is assumes a fixed view hierarchy (which seems to have changed between
iOS 6 and iOS 7).
One possible solution would be to traverse up in the view hierarchy until the table view cell is found:
UIView *view = textField;
while (view != nil && ![view isKindOfClass:[UITableViewCell class]]) {
view = [view superview];
}
EditingCell *cell = (EditingCell *)view;
A completely different, but often used method is to "tag" the text field with the row
number:
cell.textField.tag = indexPath.row; // in cellForRowAtIndexPath
and then just use that tag in the text field delegate methods.
indexPath is nil for DidSelectRowAtIndexPath when clicking on UITextField in cell
Using a similar method as this, you can get the index path of a UITextField
in a cell as so:
-(NSIndexPath *)indexPathForTextField:(UITextField *)textField
{
CGPoint textFieldMiddle = CGPointMake(CGRectGetMidX(textField.bounds), CGRectGetMidY(textField.bounds));
CGPoint point = [textField convertPoint:textFieldMiddle toView:self.tableView];
return [self.tableView indexPathForRowAtPoint:point];
}
-(void)textFieldDidChange:(UITextField *)textField
{
NSIndexPath *indexPath = [self indexPathForTextField:textField];
// Now you can update the object at indexPath for your model!
}
This is neater than relying on tag
s or looking at superview
s!
To answer the "Why did this change?" question...
iOS 7 UITableViewCell
hierarchy is different as it now contains scroll views or something inside the cell to handle the swipe to delete.
Here's a dump of the view hierarchy in iOS 7:
<CustomTableViewCell: 0x8cbc9e0; baseClass = UITableViewCell; frame = (0 0; 320 44); autoresize = W; layer = <CALayer: 0x8cbcc50>>
| <UITableViewCellScrollView: 0x8c6ceb0; frame = (0 0; 320 44); autoresize = W+H; gestureRecognizers = <NSArray: 0x8c6d0c0>; layer = <CALayer: 0x8cbce50>; contentOffset: {0, 0}>
| | <UITableViewCellContentView: 0x8cb54e0; frame = (0 0; 320 44); gestureRecognizers = <NSArray: 0x8cbb990>; layer = <CALayer: 0x8cbb7f0>>
| | | <UILabel: 0x8cbbaf0; frame = (0 0; 0 0); userInteractionEnabled = NO; layer = <CALayer: 0x8cbd000>>
| | | <UITableViewLabel: 0x8cbd210; frame = (0 0; 0 0); userInteractionEnabled = NO; layer = <CALayer: 0x8cbd360>>
| | <_UITableViewCellSeparatorView: 0x8cc2a10; frame = (15 43.5; 305 0.5); layer = <CALayer: 0x8cc26e0>>
iOS-indexPath always return nil
Try the below code
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// set Segue Identifier from your first viewcontroller to second viewController in stoaryboard
[self performSegueWithIdentifier:@"firstVCToSecondVCSegueIdentifier" sender:indexPath];
}
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:@"firstVCToSecondVCSegueIdentifier"])
{
if ([sender isKindOfClass:[NSIndexPath class]])
{
NSIndexPath *indexPath = (NSIndexPath *)sender;
if ([segue.destinationViewController isKindOfClass:[SecondVC class]]) {
SecondVC *aSecondVC = (SecondVC*)segue.destinationViewController;
NSString *name =self.nameArray[indexPath.row];
aSecondVC.title = name;
}
}
}
}
How to differenciate indexPath of first cell with indexPath of empty space at the end of table?
Is there a way to tell the difference between such a click, in the empty space at the end of the table, and a click on a "proper" cell of the table?
Yes. For the cheap and easy solution only do what you are trying to do if you actually get an indexPath:
NSIndexPath *indexPath = [tableView indexPathForRowAtPoint:p];
if(indexPath != nil){
// do everything in here
}
Basically, your indexPath is returning nil because it can't find a row. From the docs:
An index path representing the row and section associated with point, or nil if the point is out of the bounds of any row.
You could do it the way that you're currently doing it but is there any reason why you aren't using:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
This is a much more standard way of detecting the cell that the user tapped on.
This method won't be called if you tap on something that isn't a cell and has a number of other benefits. Firstly you get a reference to the tableView and the indexPath for free. But you also won't need any gesture recognisers this way either.
Try something like this:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
// Do stuff with cell here...
}
Obviously this all assumes that you have correctly set a class as your table view's delegate.
NB: It's very easy to mistakenly write didDeselectRowAtIndexPath
instead of didSelectRowAtIndexPath
when using Xcode's autocompletion to do this. I always do this and then inevitably realise my mistake 20 minutes later.
Related Topics
Checking Cellular Network Type in iOS
How to Launch IPA File in iOS 10 Real Device Using Appium 1.6.0
Swift: Is Correct to Use Stored Properties as Computed Properties
"Reached the Max Number of Texture Atlases, Can Not Allocate More" Using Google Maps
Uibutton Target Action Inside Uiview
I Want to Draw Custom Shape Like Apple Shape on UIview
I Get Nil When Using Nsdateformatter in Swift
Mpvolumeview Does Not Show Route Button on Launch
Cocos2D Sprite Repeat Animation Forever
How to Add Frameworks into the Swift Project
How to Schedule Mail Using Gmail API
CSS Flexible Box Layout on Ipad
Core Data - Fetch All Entities Using the Same Field
How to Use The Coreaudio API in Swift
Selecting All The Items in UIcollectionview iOS, Even The Cells That Are Not Visible