Identifying UISegmentedControl embedded in custom UITableViewCell when calling selector
I've a custom UITableViewCell which has a UISegmentedControl added as a subview via the cell's contentView property as follows:
#define TABLECELL_SEGMENT_TAG 1
...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UISegmentedControl *testSegmentedControl;
// Check for a reusable cell first, use that if it exists
UITableViewCell *tableCell = [tableView dequeueReusableCellWithIdentifier:@"OurCustomCell"];
// If there is no reusable cell of this type, create a new one
if (!tableCell) {
tableCell = [[[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:@"OurCustomCell"] autorelease];
// Create our segmented control
NSArray *segmentItems = [NSArray arrayWithObjects:@"Option 1", @"Option 2", nil];
UISegmentedControl *testSegmentedControl = [[UISegmentedControl alloc] initWithItems:segmentItems];
[testSegmentedControl setTag:TABLECELL_SEGMENT_TAG];
[[tableCell contentView] addSubview:testSegmentedControl];
[testSegmentedControl release];
}
// Set the selected segment status as required
testSegmentedControl = (UISegmentedControl *)[tableCell.contentView viewWithTag:TABLECELL_SEGMENT_TAG];
...
开发者_运维百科 [testSegmentedControl addTarget:self
action:@selector(segmentedControlUpdated:)
forControlEvents:UIControlEventValueChanged];
return tableCell;
}
What I need to be able to do is somewhat set the addTarget
selector for each segmented control so that it identifies the row in question, an obvious solution being to use the segmented control's tag. However as you can see I'm already using the tag to retrieve the control from within the custom cell's contentView if an existing cell is returned via the UITableView's dequeueReusableCellWithIdentifier:
method.
As such, I'm just wondering what the best way to achieve this? (I presume I could simply extend the UISegmentedControl class to add an associatedTableRow
property, but I'm wondering if there's a more elegant solution.)
Because subclassing is always the worst choice I would do the superview superview dance.
- (IBAction)controlChanged:(UIControl *)sender
NSIndexPath *indexPath = [self.tableView indexPathForCell:(UITableViewCell *)[[sender superview] superview]];
// do something
}
since iOS7 changed the view hierarchy the above code won't work. You will need to use indexPathForRowAtPoint:
:
- (IBAction)controlChanged:(UIControl *)sender {
CGPoint senderOriginInTableView = [sender convertPoint:CGPointZero toView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:senderOriginInTableView];
// do something
}
Make a subclass of UITableViewCell that has a reference to the UISegmentedControl as a property and instantiate that instead of UITableViewCell. Then you don't need the tag to refer to the segmented control and you can use it to hold the row number.
However, you could also put the row number in that subclass as a property, or even make the subclass handle the target-action. In any case, making a subclass gives you greater flexibility to handle this.
精彩评论