Uiswitch in Accessory View of a Tableviewcell, Passing a Parameter with the Selector to Have Selector Function See the Indexpath.Row

UISwitch in accessory view of a tableviewcell, passing a parameter with the selector to have selector function see the indexpath.row?

let lightSwitch = UISwitch(frame: CGRectZero) as UISwitch
lightSwitch.on = false
lightSwitch.addTarget(self, action: #selector(switchTriggered), forControlEvents: .ValueChanged)
lightSwitch.tag = indexpath.row
cell.accessoryView = lightSwitch

Let save your boolean value in Array

    func switchTriggered(sender: UISwitch) {
sender.on ? array[sender.tag]=1 : array[sender.tag]=0
}
}

How can I capture events from a Switch in a UITableViewCell?

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
}
}

What is the action for custom accessory view button - swift

Why do you need to call willSelectRowAtIndexPath? You have done everything right and to solve your unrecognized selector error just make a function that will be called when you tap on the cell.accessoryView. In your case:

func accessoryButtonTapped(){
print("Tapped")
}

Update
If you want to get the indexPath you could just

Add a tag to your cellAudioButton:

cellAudioButton.tag = indexPath.row

In your addTarget add a : to pass a parameter

And in your function

func accessoryButtonTapped(sender : AnyObject){
print(sender.tag)
print("Tapped")
}

So the whole code:

let cellAudioButton = UIButton(type: .Custom)
cellAudioButton.frame = CGRect(x: 0, y: 0, width: 20, height: 20)
cellAudioButton.addTarget(self, action: "accessoryButtonTapped:", forControlEvents: .TouchUpInside)
cellAudioButton.setImage(UIImage(named: "blueSpeaker.png"), forState: .Normal)
cellAudioButton.contentMode = .ScaleAspectFit
cellAudioButton.tag = indexPath.row
cell.accessoryView = cellAudioButton as UIView

func accessoryButtonTapped(sender : AnyObject){
print(sender.tag)
print("Tapped")
}

How can I get text from row in the UITableView?

You can add a delegate to your YourCellClass. When the switchView is toggled, call a delegate method something like this

class YourCellClass: UITableViewCell {
weak var delegate:YourCellClassDelegate?
var switchView: UISwitchView

init() {
...other stuff...
switchView.addTarget(self, action: #selector(self.switchChanged(_:)), for: .valueChanged)
...other stuff...
}

func switchChanged(_ sender : UISwitch!){
if let delegate = delegate {
delegate.cellDidToggleSwitch(self, isOn: sender.isOn)
}
}
}

protocol YourCellClassDelegate {
func cellDidToggleSwitch(_ cell: YourCellClass, isOn: Bool)
}

Then in the ViewController with the TableView

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 { // specific row showing switch
var cell = tableView.dequeueReusableCell(withIdentifier: "yourcellIdentifire", for: indexPath) as! YourCellClass
cell.textLabel?.text = "bad morning"
cell.delegate = self
return cell
}
return UITableViewCell()
}

func cellDidToggleSwitch(_ cell: YourCellClass, isOn: Bool) {
//here's your cell
}

UITableview: How to Disable Selection for Some Rows but Not Others

You just have to put this code into cellForRowAtIndexPath

To disable the cell's selection property: (while tapping the cell)

cell.selectionStyle = UITableViewCellSelectionStyleNone;

To enable being able to select (tap) the cell: (tapping the cell)

// Default style
cell.selectionStyle = UITableViewCellSelectionStyleBlue;

// Gray style
cell.selectionStyle = UITableViewCellSelectionStyleGray;

Note that a cell with selectionStyle = UITableViewCellSelectionStyleNone; will still cause the UI to call didSelectRowAtIndexPath when touched by the user. To avoid this, do as suggested below and set.

cell.userInteractionEnabled = NO;

instead. Also note you may want to set cell.textLabel.enabled = NO; to gray out the item.

Add a Selector from a UITableViewCell class to the UITableViewController class

In alternative to the accepted solution:

Depending on case you can try use delegate instead action/target

//Declare a delegate for the cell
protocol PlayerSelectionCellDelegate : class {
func playerSelectionCell(_ cell:PlayerSelectionCell, didChangeValue:Double)
func playerSelectionCell(_ cell:PlayerSelectionCell, expansionSelectionValueDidChange:Bool)
}

class PlayerSelectionCell: UITableViewCell {

weak var delegate : PlayerSelectionCellDelegate? //Set a weak var to allocate the delegate

@objc func stepperValueDidChange(_ sender: UIStepper) {
delegate?.playerSelectionCell(self, didChangeValue: sender.value)
}

@objc func expansionSelectionValueDidChange(_ sender: UISwitch) {
delegate?.playerSelectionCell(self, expansionSelectionValueDidChange: sender.isOn)
}

override func awakeFromNib() {
let stepper = UIStepper()
stepper.addTarget(self, action: #selector(stepperValueDidChange), for: .valueChanged)

//This line should be reference to the UISwitch Action
selectionSwitch.addTarget(self, action: #selector(expansionSelectionValueDidChange), for: .valueChanged)
self.accessoryView = stepper
}
}

In the ViewController you change the code to get in conformity to the delegate and set the ViewController as delegated to cell

class SetupViewController: UITableViewController {

@IBOutlet var setupTableView: UITableView!

override func numberOfSections(in tableView: UITableView) -> Int {
return 2
}

override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
switch section {
case 0:
return "Expansions"
case 1:
return "Players"
default:
return nil
}
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
switch section {
case 0:
return Expansions.allCases.count
case 1:
return 3
default:
return 0
}
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "Expansion Selection", for: indexPath) as? ExpansionCell ?? ExpansionCell()
cell.textLabel?.text = Expansions.allCases[indexPath.row].rawValue
return cell
} else if indexPath.section == 1 && indexPath.row == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "Player Selection", for: indexPath) as? PlayerSelectionCell ?? PlayerSelectionCell()
cell.delegate = self //Set the ViewController to be delegated by cell
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "Player Detail", for: indexPath) as? PlayerCell ?? PlayerCell()
cell.textLabel?.text = "Player \(indexPath.row)"
return cell
}
}

override func viewDidLoad() {
super.viewDidLoad()
}

//Remove the actions and implements the delegate methods
func playerSelectionCell(_ cell: PlayerSelectionCell, didChangeValue players: Double) {
print("Value Players: \(players)")
}

func playerSelectionCell(_ cell: PlayerSelectionCell, expansionSelectionValueDidChange selected: Bool) {
print("Value Selected: \(selected)")
}

}


Related Topics



Leave a reply



Submit