Add switch in UITableView cell in Swift
Here is way you can embed a UISwitch
on a UITableView
cell.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: "yourcellIdentifire", for: indexPath) as! YourCellClass
//here is programatically switch make to the table view
let switchView = UISwitch(frame: .zero)
switchView.setOn(false, animated: true)
switchView.tag = indexPath.row // for detect which row switch Changed
switchView.addTarget(self, action: #selector(self.switchChanged(_:)), for: .valueChanged)
cell.accessoryView = switchView
return cell
}
here is switch call beck method
func switchChanged(_ sender : UISwitch!){
print("table row switch Changed \(sender.tag)")
print("The switch is \(sender.isOn ? "ON" : "OFF")")
}
@LeoDabus
Great! explanation
.
Note: if your tableview
may have more than one section
then You should create a CustomCell subclassing UITableViewCell
and configure your accessoryView
inside UITableViewCell
awakeFromNib
method instead of table view cellForRowAt
method. When dequeuing the reusable cell
cast it to your CustomCell Here is sample from @LeoDabus
Adding a switch to each cell in a UItableview
You need to:
- Create a custom
UITableViewCell
subclass that has@IBOutlet
s for your text label andUISwitch
. - In your table view's storyboard or xib, set the type of the dynamic table view cell to the name of your custom subclass.
- In the cell's Attributes inspector, give it a custom reuse identifier.
- Drag a
UISwitch
into the dynamic cell prototype. - Connect the custom cell's outlets to the text label and switch.
- In your
tableView(_:cellForRowAt:)
implementation, instead of instantiating a table cell each time (which is almost never what you want to do), calltableView.dequeueReusableCell(withIdentifier:for:)
and pass in the custom reuse identifier that you used in step 3. Cast the returned cell to your custom type, then set the values of the outlets.
Set target for switch in custom UITableViewCell
In your code marked "Strong reference cycle" there is no strong reference cycle, so just go ahead and use it.
Where did you imagine the strong reference cycle was? Was it the use of self
as the target
? The docs say explicitly:
The control does not retain the object in the target parameter
And that is only to be expected. We'd all be in a fine pickle if you couldn't set self
as the action target for a control.
Toggle switch on TableViewCell tap
If I understand it correctly, you just want the highlight to disappear right after the tap.
If that's what you want, you can call directly deselectRow in the didSelectRowAt indexPath method:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
// Do your custom logic / toggle your switch
}
How to create a UITableViewCell with a UISwitch and get the data?
You could just add the UISwitch
in your accessory view. That is the easiest way to do it, not to mention that it looks 'elegant'.
Then, in your tableview controller code, you could just call a selector every time the switch is toggled, or even toggle the switch itself by getting the switch's current status in your controller.
Let know if you'd like a code sample.
---sample code---
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
//add a switch
UISwitch *switchview = [[UISwitch alloc] initWithFrame:CGRectZero];
cell.accessoryView = switchview;
[switchview release];
}
cell.textLabel.text = [NSString stringWithFormat:@"%d", indexPath.row];
return cell;
}
Then, you could have a method that updates a switch based on changes in your model. You could use anything you want - delegates, notifications, KVO, etc.
Example:
- (void)updateSwitchAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
UISwitch *switchView = (UISwitch *)cell.accessoryView;
if ([switchView isOn]) {
[switchView setOn:NO animated:YES];
} else {
[switchView setOn:YES animated:YES];
}
}
How can I use a switch in a tableview cell?
Clear your IBOutlet connections, connect them again and it will work ;)
How to pass state of UISwitch in prototype cell back to UITableView
First you need to create the call back in table view cell.
class ProgrammeToogleTableViewCell: UITableViewCell {
@IBOutlet weak var switchUI: UISwitch!
// callback to get action of switch status
var callBackSwitchState:((Bool) -> (Void))?
// Create action for value change event on switch
@IBAction func switchAtValueChanged(programmeToggle: UISwitch) {
callBackSwitchState?(programmeToggle.isOn)
}
}
Now in your cellForRowAt data source method, you need to set the value for this callback that you just created to get the status for your switch:
In your table view class:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) ->
UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier:
"ProgrammeToggleTableViewCell", for: indexPath) as? ProgrammeToogleTableViewCell
else { return UITableViewCell() }
cell.tag = indexPath.row
// Implement the callback to get the status of switch:
cell.callBackSwitchState = { isOn in
print("Your Switch status = \(isOn)")
// isOn is your switch status. You can update your object here.
}
// Your other code here ....
return cell
}
Related Topics
How to Pass Variable Value to Outside of Urlsession Async - Swift 3
Swift Closure Not Setting Variable
How to Rotate Only One View Controller to Landscape Orientation in iOS Swift 3
Difference Between "Precondition" and "Assert" in Swift
Remove All Non-Numeric Characters from a String in Swift
Child View Controller to Rotate While Parent View Controller Does Not
Consume Swift Package for Multiple Targets and Platforms in a Project
How to Read a File in a Swift Playground
How to Declare That a Computed Property 'Throws' in Swift
Difference Between Force Unwrapping Optionals and Implicitly Unwrapped Optionals
Why Can the Keyword "Weak" Only Be Applied to Class and Class-Bound Protocol Types
New @Convention(C) in Swift 2: How to Use It
Use Cocoapods With an App Extension
How to Open Your App in Settings iOS 11
How to Print a String from Plist Without "Optional"