Reputation: 313
I am using a customized TableViewCell
in my App. It works fine with IOS 6 but I got error in ios 7. Error occurred when I access sub views of UITableViewCell
see the code below where I got error
- (void)addButtonClicked:(UIButton *)button {
Product *product = [productsArray objectAtIndex:button.tag];
NSString *code = product.code;
OTATableCell *cell = (OTATableCell *) [[button superview] superview];
cell.priceLabel; // here i get error
}
error shown is:
-[UITableViewCellScrollView priceLabel]: unrecognized selector sent to instance 0x15d0ff80
Please help me to solve this problem. Thanks in advance.
Upvotes: 2
Views: 721
Reputation: 5268
You can access tableview cell based upon access, regardless of the version you are using in it.This Code will work independent of the OS it is running.
UITableViewCell *cell;
UIView * targetView;
id superView = [targetView superview];
while (![superView isKindOfClass:[UITableViewCell class]])
{
superView = [superView superview];
}
cell = (UITableViewCell *)superView;
Now cell
holds UITableViewCell
Upvotes: 0
Reputation: 3588
Relying on the order of sub views of any inbuilt control is not a good idea as its Apple's territory and they can change it anytime without any notice as they did in iOS 7.
You can inherit UIButton
class and add a property of class NSIndexPath
. While creating the cell in cellForRowAtIndexPath:
method assign the value of input parameter indexpath
to this property.
When the button is tapped, use the method [tableView cellForRowAtIndexPath:indexPath]
to get the cell. This method returns the object of class UITableViewCell
, and in your case, the custom cell class.
Hope this helps!
Upvotes: 0
Reputation: 4561
Need one more superView
call:
OTATableCell *cell = (OTATableCell *)[[[button superview] superview] superview];
You can check something like:
For iOS >= 7:
NSLog(@"%@",[[sender superview] class]); //UITableViewCellContentView
NSLog(@"%@",[[[sender superview] superview] class]); //UITableViewCellScrollView
NSLog(@"%@",[[[[sender superview]superview]superview] class]); //UITableViewCell
For iOS < 7:
NSLog(@"%@",[[sender superview] class]); //UITableViewCellContentView
NSLog(@"%@",[[[sender superview] superview] class]); //UITableViewCell
NSLog(@"%@",[[[[sender superview]superview]superview] class]); //UITableView
Edit:If you don't want to rely on superView
property:
UIButton *button = (UIButton *)sender;
CGRect buttonFrame = [button convertRect:button.bounds toView:self.table];
NSIndexPath *indexPath = [self.table indexPathForRowAtPoint:buttonFrame.origin];
//Access the cell using indexPath
:
UITableViewCell *cell=[self.table cellForRowAtIndexPath:indexPath];
cell.label=@"setText";
Upvotes: 4
Reputation: 522
Obviously your problem is that Apple never promised you what the structure of a cell will be in different versions of iOS. So, it's a bad idea to rely on superview's superview. If you need to access a label in same cell as a button, keep the reference to it as a buttons property. I mean
@interface MyButton:UIButton
@property (nonatomic, weak) UILabel* priceLabel;
@end
And assign this property when configure the cell.
And remember: never hard cade versions! Like <7.0 and >=7.0, because you don't know what version 8.0 will look like.
Upvotes: 0
Reputation: 90117
You must not rely on the view hierarchy in classes that start with UI. The view hierarchy in those classes can and will change without notice. Don't do the superview dance. Maybe Apple will change the view hierarchy in iOS8 again.
There is a much better way to do this. You can ask the tableView for the indexPath of a specific point in your tableview. You can get this point by converting the buttons frame. This will always work, because it does not rely on implementation details.
You do it like this:
- (void)addButtonClicked:(UIButton *)button {
CGPoint buttonOriginInTableView = [button convertPoint:CGPointZero toView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonOriginInTableView];
Product *product = [productsArray objectAtIndex:indexPath.row];
NSString *code = product.code;
OTATableCell *cell = (OTATableCell *)[self.tableView cellForRowAtIndexPath:indexPath];
cell.priceLabel;
}
Upvotes: 0
Reputation: 4345
Though you have the correct answer but i strongly disagree doing juglry with superviews. And more over going the standard OOPS way it is very easy to do desired customization.
you can create a uitableviewcell subclass
do all initialization in its
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
method and save and use reuseIdentifier
to identify and change your cell appearance. this way you will have flexibility of adding n number of methods in your cell and still keeping your cell for row method clean.
Upvotes: 0
Reputation: 1620
Problem is Table view cells sub views. In ios 7 there is one extra content view so you need to check for one more super view
float fVersion=[[[UIDevice currentDevice] systemVersion] floatValue];
if(fVersion>=7.0)
{
OTATableCell *cell = (OTATableCell *)[[[button superview] superview] superview];
}
else
{
OTATableCell *cell = (OTATableCell *)[[button superview] superview];
}
Or
in cellForRowAtIndexPath,
set the Accessibility Identifier for the button which you are added on the cell as below
[button setAccessibilityIdentifier:[NSString stringWithFormat:@"%d",indexPath.row]];
Then where you want to access the cell use below code
NSIndexPath *iIndexRowId =[NSIndexPath indexPathForRow:[[button accessibilityIdentifier] intValue] inSection:0];
OTATableCell *objCell1=(OTATableCell*)[_YouTableName cellForRowAtIndexPath:iIndexRowId];
Upvotes: 1