How to trigger UITableViewCell editActions programmatically? [duplicate] - ios

This question already has answers here:
Open UITableView edit action buttons programmatically
(5 answers)
Closed 5 years ago.
I have made a few custom edit actions on my tableviewcell. It works fine when I swipe, but I was wondering if there was any way to trigger these actions when I tap the cell. Also, I have seen lots of people answer similar questions with just,
tableView.setEditing(true, animated: true)
though this is not the solution I am looking for. I want the actions to immediately get displayed without the press of another button.

Short answer is - there is no such way.
However, if you really need something like that, you can mimic this behaviour, though it requires lot more implementation and state handling on your own.
Here is a quick and very dirty solution, which overrides touchesEnded method of your custom cell. Remember to set up Cell as a dynamic prototype of the cell in your table view in relevant storyboard and set its reuse identifier to identitifer.
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, CellDelegate {
#IBOutlet weak var tableView: UITableView?
override func viewDidLoad() {
super.viewDidLoad()
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "identifier") as? Cell else {
return UITableViewCell()
}
cell.textLabel?.text = "\(indexPath.row)"
cell.indexPath = indexPath
cell.delegate = self
return cell
}
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
return nil
}
func doAction(for cell: Cell) {
let indexPath = cell.indexPath
print("doing action for cell at: \(indexPath!.row)")
// your implementation for action
// maybe delete a cell or whatever?
cell.hideFakeActions()
}
}
protocol CellDelegate: class {
func doAction(for cell: Cell)
}
class Cell: UITableViewCell {
weak var delegate: CellDelegate?
var indexPath: IndexPath!
#IBOutlet weak var buttonAction1: UIButton?
#IBOutlet weak var constraintButtonFakeActionWidth: NSLayoutConstraint?
override func awakeFromNib() {
self.constraintButtonFakeActionWidth?.constant = 0
}
override func touchesEnded(_ touches: Set<UITouch>,
with event: UIEvent?) {
guard let point = touches.first?.location(in: self) else {
return
}
if self.point(inside: point, with: event) {
print("event is in cell number \(indexPath.row)")
self.showFakeActions()
}
}
func showFakeActions() {
self.constraintButtonFakeActionWidth?.constant = 80
UIView.animate(withDuration: 0.3) {
self.layoutIfNeeded()
}
}
func hideFakeActions() {
self.constraintButtonFakeActionWidth?.constant = 0
UIView.animate(withDuration: 0.3) {
self.layoutIfNeeded()
}
}
#IBAction func fakeAction() {
delegate?.doAction(for: self)
}
}
So how does it work? Each cell is a UIView which inherits from abstract UIResponder interface. You can override its methods to do actions on your own on behalf of events that are dispatched to them. This is the first step where you override touchesEnded.
Take a look at the screenshot from interface builder - you have to hook up the constraint.
I've also implemented the delegate which returns nil for all edit actions of the cells, so they don't interfere with your workaround.
Next, you set up a custom delegate to get a callback from the cell. I also attached IndexPath to the cell for the convenience of managing data in the dataSource, which you have to implement.
Remember that this code lacks a lot, like prepareForReuse method implementation. Also, you probably want to do additional checks in touchesEnded override which would guarantee that this delegate callback is not fired more than once per touch and prevent multiple touches. The logic for disabling user interaction on a cell is not implemented here as well. And interface requires fine-tuning (like text appears to be squashed during the animation).

Related

UISegmentedControl in each UITableViewCell of UITableView

I'm trying to implement UISegmentedControl in each dequeueReusableCell UITableViewCell like so:
The Issue: Each TableViewCell is referencing to the same Segmented Control and I'm unable to fetch the state of the control for any cell in particular. As per my understanding, there's only one instance of SegmentedControl that is being initialised and that instance is being shared by all the TableViewCells, and because of that I can't access the unique value of the state for any particular TableViewCell, eg: I'm unable to access what the SegmentControl state is set to for the 3rd cell.
View Controller Code:
import UIKit
import UserNotifications
class MarkAttendanceViewController: UIViewController {
var pickedDate: Date = Date.init()
override func viewDidLoad() {
super.viewDidLoad()
if #available(iOS 13.0, *) {
overrideUserInterfaceStyle = .light
}
}
#IBAction func datePicker(_ sender: UIDatePicker) {
pickedDate = sender.date.addingTimeInterval(19800)
let weekDay = Calendar(identifier:.gregorian).component(.weekday, from: pickedDate)
print(weekDay)
updateSubjects(pickedDate)
}
func updateSubjects(_ pickedDate: Date) {
}
}
extension MarkAttendanceViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "subjectCell", for: indexPath) as! SubjectTableViewCell
cell.SessionType.text = "Lecture"
cell.SessionName.text = "Network Security"
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
}
}
class SubjectTableViewCell: UITableViewCell {
#IBOutlet var SessionType: UILabel!
#IBOutlet var SessionName: UILabel!
#IBOutlet var segmentControlOutlet: UISegmentedControl!
#IBAction func segmentedControlIndex(_ sender: UISegmentedControl) {
print(sender.selectedSegmentIndex)
}
}
Github Link here
Please let me know if there's any more information that I need to provide or if the question isn't clear. TIA
You should set the tag of your segmentControlOutlet to indexPath.row in cellForRowAt:IndexPath method.
Also you must add an action on valueChange event on each of your UISegmentedControl in the same method.
below code might give you some idea:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "subjectCell", for: indexPath) as! SubjectTableViewCell
cell.SessionType.text = "Lecture"
cell.SessionName.text = "Network Security"
// add an action on value change to detect a change in the value of segmented control
cell.segmentControlOutlet.addTarget(self, action: #selector(segmentValueChanged(_:)), for: .valueChanged)
// set the tag property of your segmented control to uniquely identify each segmented control in the value change event
cell.segmentControlOutlet.tag = indexPath.row
return cell
}
and you can distinguish among various instances of UISegmentedControl using the tag property that you set inside the cellForRow method.
#objc func segmentValueChanged(_ sender: UISegmentedControl) {
switch sender.tag {
case 0:
// do something on value changed in segmented control in first cell and so on...
print(sender.tag)
default:
break
}
print(sender.selectedSegmentIndex)
}
Hope this helps
Use this toterial. add UITableViewCell to your project and set UISegment action in custom UITableViewCell
it seems that the root cause of the issue that would like to pass the data between the cell and the VC containing the table and this is done simple by delegate and protocol design pattern as below
you will have a protocol defining the data to be passed between two members as below
protocol SubjectTableViewCellDelegate {
func didSelectSegmentControlCell(cell: SegmentCell)
}
then you will have cell containing the segment control and a delegate var of type SegmentControlDelegate as below
import UIKit
class SubjectTableViewCell: UITableViewCell {
// MARK: Properties
var delegate: SubjectTableViewCellDelegate?
// MARK: IBOutlets
#IBOutlet weak var segmentControl: UISegmentedControl!
// MARK: Life Cycle Methods
override func awakeFromNib() {
super.awakeFromNib()
}
// MARK: IB Actions
#IBAction func segmentControlAction(_ sender: UISegmentedControl) {
delegate?.didSelectSegmentControlCell(cell: self)
}
}
then you will have your VC acting as a delegate of the Segment cell after having each cell delegate to be the VC containing the Table
import UIKit
class MarkAttendanceViewController: UIViewController, SegmentCellDelegate, UITableViewDelegate, UITableViewDataSource {
// MARK: SegmentCellDelegate Methods
func didSelectSegmentControlCell(cell: SegmentCell){
// you will have the cell that contains all the data
/* all your business here */
}
extension MarkAttendanceViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "subjectCell", for: indexPath) as! SubjectTableViewCell
/* remember to have thee delegate of the cell to self as the below line */
cell.delegate = self
cell.SessionType.text = "Lecture"
cell.SessionName.text = "Network Security"
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
}
}
}
the idea is a general idea imagine there is a button or date picker or any other outlet you should use this pattern to move data between two sides
I would suggest that the answers you have been given, including the accepted answers, are quick fixes that don't actually address the real problem with how you have architected this piece of software. You may not care at this point, but for future readers of the question this may be helpful.
You may have heard of the Model-View-Controller (MVC) architecture that is commonly used when developing for the iOS platform. In the case of your software you have a View -- for simplicity's sake, let's just consider the table view cells as the view in this case. You have a controller -- your MarkAttendanceViewController which implements the UITableViewDataSource and UITableViewDelegate interfaces. The issue, however, is that you don't really have a model for the data you are displaying in the view. In fact, the root of your problem stems from the fact that you are using the view as the model as well, which is problematic because table view cells are reused and the data contained in them can be lost during the cell reuse process if it is not stored somewhere else. If the data is stored in a data model class, you can keep it separate from the table view cells and it will persist through cell reuse.
You have 3 pieces of data associated with each table view cell: The SessionType, the SessionName and the attendance status for the session (ie: Attended, Missed, Mass Bunk or No Lecture). A data model for this could look like this (with an enumerated type to represent the attendance status):
enum AttendanceStatus: Int {
case attended
case missed
case massBunk
case noLecture
}
struct Session {
let name: String
let type: String
var attendanceStatus: AttendanceStatus
}
You may also want to represent type with an enum, but let's keep this simple.
You can instantiate an instance of this data model as follows:
var session = Session(name: "Network Security", type: "Lecture", attendanceStatus: .attended)
Note the var keyword to make it mutable, as you will want to change the attendanceStatus when the UISegmentedControl value changes. Changing this property is done like so:
session.attendanceStatus = .noLecture
To map from your segmented control to AttendanceStatus, you can use the Int raw value for the enum, as follows:
AttendanceStatus(rawValue: segmentedControl.selectedSegmentIndex)
And to map from your data model's attendanceStatus property to a selectedSegmentIndex for your segmented control:
segmentedControl.selectedSegmentIndex = session.attendanceStatus.rawValue
Now in your view controller, you can instantiate an array of Session objects and use that to populate your table view. When a segmented control changes, you can use the indexPath.row of the table view cell for the segmented control in order to find the Session instance in your array of sessions!
(For a more advanced implementation of this, you can also looking into the Model-View-ViewModel (MVVM) architecture which provides an even cleaner way of bidirectional mapping between the data model and the view)
There are multiple way to solve this Problem.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "subjectCell", for: indexPath) as! SubjectTableViewCell
cell.SessionType.text = "Lecture"
cell.SessionName.text = "Network Security"
// add an action on value change to detect a change in the value of segmented control
cell.segmentControlOutlet.addTarget(self, action: #selector(segmentChanged(_:)), for: .valueChanged)
// set the tag property of your segmented control to uniquely identify each segmented control in the value change event
cell.segmentControlOutlet.tag = indexPath.section
return cell
}
Then Find cell based on Segment Control.
#objc func segmentChanged(_ sender: UISegmentedControl) {
if let cell = sender.superview as! UITableViewCell {
let indexPath = tableView.indexPathForCell(cell)
print(indexPath.row)
if indexPath.row == 0 {
print("segment event of cell 0")
}
else if indexPath.row == 1 {
print("segment event of cell 1")
}
}
}
you can also use delegate and Clouser

Prevent UITableViewCells from highlighting when panning

I am using a UIViewController which contains a ContainerView. Inside the ContainerView I have a UITableViewController. I have a PanGestureRecognizer in my UIViewController which I use for dismissing it. Now the problem I have is that when I pan to close the UIViewController, the TableViewCells inside UITableViewController that are touched become briefly highlighted.
I have disabled scrolling in my tableview as I don't need it.
I added this to my pan gesture handler's .began but it didn't have any effect:
myTableView.isUserInteractionEnabled = false
I also tried:
myGestureRecognizer.cancelsTouchesInView = true
but the touches are still passed to the TableView and cause the cells to become highlighted. Is there any solution for this?
I ended up using this:
myGestureRecognizer.delaysTouchesBegan = true
It may not be useful in every situation, but for my TableView it prevents the highlights from happening.
You could try immediately deselecting rows that are selected in the delegate method for didSelectRow.
extension MyViewController: UITableViewDelegate {
public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
}
}
Will prevent cells from being highlighted when selected. From my experience, this is somewhat common practice.
EDIT: My mistake, misread the question. In which case, you could consider using the tableView's scrollView delegate to determine when you're scrolling, and disable interaction on the individual cells like so:
class ViewController: UIViewController {
private var areCellsDisabled = false {
didSet {
tableView.reloadData()
}
}
// Rest of your view controller logic here...
}
extension ViewController: UITableViewDelegate {
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
areCellsDisabled = true
}
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
areCellsDisabled = false
}
}
extension ViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Configure/dequeue the cell, etc.
if areCellsDisabled {
cell.isUserInteractionEnabled = false
} else {
cell.isUserInteractionEnabled = true
}
return cell
}
}
This might be taking a hammer to the problem, though. Let me know if it helps.

How to get the indexPath.row when I click a button on a table view cell?

Hello the image above is the UI of my todo list app, now I just want to show the detail of item (First Item, second Item etc) when I click the detail button in the tableviewcell. So in order to get the property of the item, I need to know the indexPath of the row that I just clicked on the detail button.
I have tried some properties of the tableview like didSelectRowAt, or indexPathForSelectedRow, but both not work. For didSelectRowAt user need to click on the row first then click the detail button, and that's not what I want, and the indexPathForSelectedRow is not working for me.
A common, generalized solution for this type of problem is to connect the #IBAction of the button to a handler in the cell (not in the view controller), and then use a delegate-protocol pattern so the cell can tell the table when the button was tapped. The key is that when the cell does this, it will supply a reference to itself, which the view controller can then use to determine the appropriate indexPath (and thus the row).
For example:
Give your UITableViewCell subclass a protocol:
protocol CustomCellDelegate: class {
func cell(_ cell: CustomCell, didTap button: UIButton)
}
Hook up the #IBAction to the cell (not the view controller) and have that call the delegate method:
class CustomCell: UITableViewCell {
weak var delegate: CustomCellDelegate?
#IBOutlet weak var customLabel: UILabel!
func configure(text: String, delegate: CustomCellDelegate) {
customLabel.text = text
self.delegate = delegate
}
#IBAction func didTapButton(_ button: UIButton) {
delegate?.cell(self, didTap: button)
}
}
Obviously, when the cell is created, call the configure method, passing, amongst other things, a reference to itself as the delegate:
extension ViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { ... }
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! CustomCell
let text = ...
cell.configure(text: text, delegate: self)
return cell
}
}
Finally, have the delegate method call indexPath(for:) to determine the index path for the cell in question:
extension ViewController: CustomCellDelegate {
func cell(_ cell: CustomCell, didTap button: UIButton) {
guard let indexPath = tableView.indexPath(for: cell) else { return }
// use `indexPath.row` here
}
}
The other approach is to use closures, but again using the same general pattern of hooking the button #IBAction to the cell, but have it call a closure instead of the delegate method:
Define custom cell with closure that will be called when the button is tapped:
class CustomCell: UITableViewCell {
typealias ButtonHandler = (CustomCell) -> Void
var buttonHandler: ButtonHandler?
#IBOutlet weak var customLabel: UILabel!
func configure(text: String, buttonHandler: #escaping ButtonHandler) {
customLabel.text = text
self.buttonHandler = buttonHandler
}
#IBAction func didTapButton(_ button: UIButton) {
buttonHandler?(self)
}
}
When the table view data source creates the cell, supply a handler closure:
extension ViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { ... }
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! CustomCell
let text = ...
cell.configure(text: text, buttonHandler: { [weak self] cell in // the `[weak self]` is only needed if this closure references `self` somewhere
guard let indexPath = tableView.indexPath(for: cell) else { return }
// use `indexPath` here
})
return cell
}
}
I personally prefer the delegate-protocol pattern, as it tends to scale more nicely, but both approaches work.
Note, in both examples, I studiously avoided saving the indexPath in the cell, itself (or worse, “tag” values). By doing this, it protects you from getting misaligned if rows are later inserted and deleted from the table.
By the way, I used fairly generic method/closure names. In a real app, you might give them more meaningful names, e.g., didTapInfoButton, didTapSaveButton, etc.) that clarifies the functional intent.
Implement the delegate method tableView(_:accessoryButtonTappedForRowWith:)
func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath)
However if you want to navigate to a different controller connect a segue to the accessory view button
If the button is a custom button see my answer in Issue Detecting Button cellForRowAt

Can't get didSelectRowAt to work for TableView

I am having trouble getting the didSelectRowAt method to work for a TableView inside of a regular ViewController. I have already made sure that the delegate and data source for the table are set in the ViewController code. This ViewController populates the tableview cells with results from a search query to an API, and the rendering of cell data is working fine.
It's just the didSelectRowAt method that is not registering. I did try manually adding the same delegate information on the Main.storyboard, but the little + sign won't trigger any popup windows. I am wondering if there is something in the Main.storyboard that needs fixing. I have attached the images of the ViewController and TableView connections inspector as well. I am new to iOS development and don't have much experience with graphic interfaces for mobile design, so I am assuming it's something there but maybe I am wrong.
Here's the basic version of my code:
class SearchViewController: UIViewController, UISearchBarDelegate, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
#IBOutlet var searchBar: UISearchBar!
...variable declarations ....
override func viewDidLoad() {
super.viewDidLoad()
self.hideKeyboardWhenTappedAround()
searchResults = []
searchBar.delegate = self
tableView.dataSource = self
tableView.delegate = self
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1;
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return searchResults!.count;
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "searchTableViewCell", for: indexPath) as! SearchTableViewCell
if(searchActive && !(self.searchResults?.isEmpty)!) {
(doing some stuff with search results here...works fine)
}
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("hello!")
}
func searchBar(_ searchBar: UISearchBar,
textDidChange searchText: String) {
print("search text \(searchText)")
getSearchResultJSON(term: searchText) { json in
let data = json as! [Dictionary<String, String>]
self.searchResults = data
}
self.tableView.reloadData()
}
...
}
[]
[]
EDIT: as a sanity check for if the search asynchronous function was changing anything, I just tried removing all search-related code and filling the tableview from a hardcoded dummy variable array. It worked to display the dummy variables, but still no ability to select a cell and get any reaction. I also saw a couple mentions that I had previously had a typo with didDeSelectRowAt instead of didSelectRow at, that has been fixed but the behaviour is the same.
This ended up being related to a tap gesture that occurs in the hideKeyboardWhenTappedAround() extension that I wrote
Found it! The culprit was the self.hideKeyboardWhenTappedAround(), which is an extension I wrote to hide the keyboard. This interfered with the tap of a cell because it did indeed utilize UITapGestureRecognizer. Thanks for the hints everyone.
You are using didDeselectRowAt instead of didSelectRowAt
Edit
Well, use this below delegate then
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
and make your controller conform to UIGestureRecognizerDelegate
If you are using tap gesture on main view then table view cell did select method is not working properly.
In picture you uploaded, delegate and datasource aren't connected to the ViewController.
Remove the code in viewdidload (tableview.delegate = self) and connect them in storyboard.

Update the state of a UISwitch when pressed in a TableView

I have an iOS application that needs to turn on/off lights remotely. The app gets the data for the lights from parse.com and builds a tableview with every individual cell showing the name of the light and a UISwitch. I want to know how to change the boolean value stored on parse.com when I switch on or off one of the lights. The problem is that the IBAction used by the switch is not boolean and I cannot write and if statement that updates the value of the light is the switch is pressed. I have created the IBaction in my cell class and hoped that could be used by the tableviewcontroller class.
Here is part of my tableviewcontroller class
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:RelayCell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as RelayCell
let label:PFObject = self.labelArray.objectAtIndex(indexPath.row) as PFObject //create the object label
cell.relayTextField.text = label.objectForKey("text") as String //put the text in the labeltextField
if (label.objectForKey("switch") as NSObject == 1) {
//cell.mySwitch = true //turn the switch on depending on the boolean value in switchColumn
cell.mySwitch.setOn(true, animated: true)
}
else{
//cell.mySwitch = false //turn the switch on depending on the boolean value in switchColumn
cell.mySwitch.setOn(false, animated: true)
}
return cell
}
This code shows the state of each independent switch however, what I want now is to be able to press on each independent button on the app and change the value on the online database.
Could you help me out since I haven't found anything online.
class RelayCell: UITableViewCell {
#IBOutlet weak var mySwitch: UISwitch!
#IBOutlet weak var relayTextField: UITextField!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
relayTextField.layer.borderColor = UIColor.blackColor().CGColor
relayTextField.layer.borderWidth = 0.8
relayTextField.layer.cornerRadius = 10
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
#IBAction func switchChangedState(sender: UISwitch) {
}
}
This is my RelayCell class that is used by the tableView method in the tableViewController class.
One way to handle this is to add a callback property to RelayCell and to call the callback from switchChangedState:
class RelayCell: UITableViewCell {
typealias SwitchCallback = (Bool) -> Void
var switchCallback: SwitchCallback?
#IBAction func switchChangedState(sender: UISwitch) {
switchCallback?(sender.on)
}
// ... rest of RelayCell
}
In your tableView:cellForRowAtIndexPath: method, set the cell's callback:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:RelayCell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as RelayCell
cell.switchCallback = { [weak self] (switchIsOn) in
self?.setSwitchValue(switchIsOn, forRowAtIndexPath:indexPath)
Void()
}
// ... rest of tableView:cellForRowAtIndexPath:
return cell
}
Then you can do whatever you need in setSwitchValue:forRowAtIndexPath:, which is a method you add to your table view controller class:
private func setSwitchValue(switchIsOn: Bool, forRowAtIndexPath indexPath: NSIndexPath) {
println("row \(indexPath.row) switch on-ness is now \(switchIsOn)")
}
UISwitch has "on" property, use it to get the boolean value for current state.

Resources