In Xcode 8.3.2 Swift 3.1, I have a UITableView where each row contains a label and a switch. I can manage the switches as a group (process the array), but what I would really like is to have a ValueChanged event fire in the parent UIViewController when one of the switches is changed, indicating which row changed. However, with the Switch being in a UITableViewCell, I'm not sure how to relay the event to the parent UIViewController. Thanks.
-
See http://stackoverflow.com/a/39566554/1271826 for an example of Duncan's first suggestion. – Rob May 04 '17 at 01:32
1 Answers
There are various solutions to this.
One is to set up a custom subclass of UITableView where the switch is linked to the cell. Then set up the cell to have a delegate property, and make the cell send a message to it's delegate when the user taps the switch.
Another option is to set the target/action on your cell's switches to invoke a method in your view controller in the cellForRow(at:)
method. However you need to leave the action blank in interface builder and use the control's allTargets property to check to see if the switch (or button or other UIControl) already has a target/action. (If you blindly add a target/action each time in cellForRow(at:)
you'll wind up with multiple target/actions, one for each time a cell gets recycled.
A third option is to set up a custom subclass of your control (UISwitch in this case) that takes has a closure property that it invokes when it's action is triggered. You'd make such a control set itself as the target and make the action invoke the closure if is was not nil. Your cellForRow(at:)
method could then install a custom closure that did whatever you want when the control is triggered.
Note that regardless of which approach you use you need a way to figure out which indexPath represents the switch who's value changed.
In my answer to this SO question I outline a general-purpose way to figure out which cell contains a view. It would work to figure out which cell contains the switch the user tapped in your case.
I outline a simple extension to UITableView
that lets you figure out which IndexPath
(if any) contains a particular UIView
.
The gist of it is that you can create a simple extension to UITableView
that lets you figure out the IndexPath
of the cell that contains any UIView
The code looks like this:
public extension UITableView {
/**
This method returns the indexPath of the cell that contains the specified view
- Parameter view: The view to find.
- Returns: The indexPath of the cell containing the view, or nil if it can't be found
*/
func indexPathForView(_ view: UIView) -> IndexPath? {
let origin = view.bounds.origin
let viewOrigin = self.convert(origin, from: view)
let indexPath = self.indexPathForRow(at: viewOrigin)
return indexPath
}
}

- 128,072
- 22
- 173
- 272