Shaheer Palollathil
Shaheer Palollathil

Reputation: 313

TableViewCell subviews can't access in IOS 7

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

Answers (7)

Vinodh
Vinodh

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

Yogi
Yogi

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

Preetam Jadakar
Preetam Jadakar

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

user2260054
user2260054

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

Matthias Bauch
Matthias Bauch

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

amar
amar

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

Suyog Patil
Suyog Patil

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

Related Questions