How do I retrieve UITableView row number of a UISwitch?

时光怂恿深爱的人放手 提交于 2019-12-01 05:54:51

Tags is an okay solution, but a little clumsy because the cells - and therefore their subviews - are continually being reused, changing their rows - and therefore the tags they need.

Instead, I generally keep one of these around:

- (NSIndexPath *)indexPathWithSubview:(UIView *)subview {

    while (![subview isKindOfClass:[UITableViewCell self]] && subview) {
        subview = subview.superview;
    }
    return [self.tableView indexPathForCell:(UITableViewCell *)subview];
}

Then when I get an IBAction:

- (IBAction)someSubviewAction:(id)sender {

    NSIndexPath *indexPath = [self indexPathWithSubview:(UIView *)sender];
    // carry on from here
}

You may set switch view tag to row index. Instead of theSwitch.tag = 100;

do

-(UITableViewCell*)tableView:table cellForRowAtIndexPath:indexPth
{
    UISwitch *theSwitch = nil;
    if (cell == nil) {
        ...
        // as per your example
        [cell.contentView addSubview:theSwitch];
    } else {
        theSwitch = subviewWithClass(cell.contentView, [UISwitch class]);
    }

    theSwitch.tag = indexPath.row;
    ...
}

Add this helper function to replace viewWithTag: call

UIView *subviewWithClass(UIView *contentview, Class klass)
{
    for (UIView *view in contentview.subviews)
        if ([view isKindOfClass:klass])
            return view;
    return nil;
}

Then retrieve tag, that is a row index now, in your switchChanged function

-(IBAction)switchChanged:(UISwitch *)sender {
    NSLog(@"Selected Switch - %d", sender.tag);
    ...
 }

If you use something block-based (like https://github.com/brightsoftdev/iOS-Block-Based-Bindings/blob/master/UISwitch%2BBindings.m), you don't need to worry about getting the row, because you can reference the indexPath that is passed into tableView:cellForRowAtIndexPath: in your block.

Similar to @danh, I've come up with this solution using an extention which I've used multiple times.

@interface UIView (Find)
- (id)findSuperviewOfClass:(Class)class;
- (NSIndexPath *)findIndexPath;
@end

@implementation UIView (Find)
- (id)findSuperviewOfClass:(Class)class
{
    return [self isKindOfClass:class] ? self : [self.superview findSuperviewOfClass:class];
}

- (NSIndexPath *)findIndexPath
{
    UITableView *tableView = [self findSuperviewOfClass:[UITableView class]];
    return [tableView indexPathForCell:[self findSuperviewOfClass:[UITableViewCell class]]];
}
@end

for iOS6+ you could maintain a NSMutableArray queuedSwitches

in -tableView:cellForrowAtIndexPath: you would take a switch, if not empty and places it on the custom cell and assign it to a property. If empty you create a new one.

in -tableView:didEndDisplayingCell:forRowAtIndexPath: you would add it to quededSwitches and remove it from it cell.

This will just allocate enough switches for visible cells and reuse them.

the switches are all wired up to one action.

-(void)switchAction:(UISwitch *)switch 
{
    NSIndexPath *indexPath = [self.tableView indexPathForCell:[switch superView]];

    //…
}

You could create a subclass of UISwitch and add an indexPath property, then just set the indexPath in cellForRowAtIndexPath:

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    SwitchCell *returnCell = [tableView dequeueReusableCellWithIdentifier:@"SwitchCell" forIndexPath:indexPath];
    returnCell.switch.indexPath = indexPath;

    return returnCell;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!