How can I get index path of cell on switch change event in section based table view
In your custom cell add properties which help you identify the information the cell represents. Index path, indexes for your data model etc...
Then add a block property to the cell which you can call to tell a UITableView or any other piece of code when a cell switch changes. e.g.
@property (nonatomic,copy) void (^onSwitchChange)(UITableViewCell *cell);
Inside your custom cell code, add an action handler for the UISwitch. When it fires, call self.onSwitchChange(self) which will notify the code which registered an onSwitchChange block that a switch has changed and on which cell.
In your table view when you create the cell, set the onSwitchChange block as follows:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath (NSIndexPath *)indexPath
{
<snip>
YourUITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:yourCellIdentifier forIndexPath:indexPath];
cell.onSwitchChange=^(UITableViewCell *cellAffected){
// Add code to deal with the swicth switch using properties of cellAffected
... Your handler code here ...
}];
<snip>
}
This lets you handle all the changes in the table view controller. Hope this helps.
How can I keep track of the index path of a button in a table view cell?
I have created one Method for getting indexPath, Hope this will help you.
Create Button Action (aMethod:) in cellForRowAtIndexPath
-(void) aMethod:(UIButton *)sender
{
// Calling Magic Method which will return us indexPath.
NSIndexPath *indexPath = [self getButtonIndexPath:sender];
NSLog(@"IndexPath: %li", indexPath.row);
NSLog(@"IndexRow: %li", indexPath.section);
}
// Here is the Magic Method for getting button's indexPath
-(NSIndexPath *) getButtonIndexPath:(UIButton *) button
{
CGRect buttonFrame = [button convertRect:button.bounds toView:groupTable];
return [groupTable indexPathForRowAtPoint:buttonFrame.origin];
}
How to get the indexpath.row when an element is activated?
giorashc almost had it with his answer, but he overlooked the fact that cell's have an extra contentView
layer. Thus, we have to go one layer deeper:
guard let cell = sender.superview?.superview as? YourCellClassHere else {
return // or fatalError() or whatever
}
let indexPath = itemTable.indexPath(for: cell)
This is because within the view hierarchy a tableView has cells as subviews which subsequently have their own 'content views' this is why you must get the superview of this content view to get the cell itself. As a result of this, if your button is contained in a subview rather than directly into the cell's content view, you'll have to go however many layers deeper to access it.
The above is one such approach, but not necessarily the best approach. Whilst it is functional, it assumes details about a UITableViewCell
that Apple have never necessarily documented, such as it's view hierarchy. This could be changed in the future, and the above code may well behave unpredictably as a result.
As a result of the above, for longevity and reliability reasons, I recommend adopting another approach. There are many alternatives listed in this thread, and I encourage you to read down, but my personal favourite is as follows:
Hold a property of a closure on your cell class, have the button's action method invoke this.
class MyCell: UITableViewCell {
var button: UIButton!
var buttonAction: ((Any) -> Void)?
@objc func buttonPressed(sender: Any) {
self.buttonAction?(sender)
}
}
Then, when you create your cell in cellForRowAtIndexPath
, you can assign a value to your closure.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell") as! MyCell
cell.buttonAction = { sender in
// Do whatever you want from your button here.
}
// OR
cell.buttonAction = buttonPressed(closure: buttonAction, indexPath: indexPath) // <- Method on the view controller to handle button presses.
}
By moving your handler code here, you can take advantage of the already present indexPath
argument. This is a much safer approach that the one listed above as it doesn't rely on undocumented traits.
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
}
Allows to choose only one option switch button inside table view
You would want to add a property in your view controller that would keep track of the selected switch
var selectedSwitchIndex: Int?
And in your cellForRowAt
method, set the selected switch to On and keep other switches off.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "answerListCell", for: indexPath) as! AnswerListTableViewCell
cell.separatorInset.right = cell.separatorInset.left
cell.answerList.optionSwitch.tag = indexPath.row
cell.answerList.optionSwitch.addTarget(self, action: #selector(self.switchChanged(_:)), for: .valueChanged)
let isSelected = indexPath.row == selectedSwitchIndex
cell.answerList.optionSwitch.isOn = isSelected
return cell
And in your switchChanged
method, set the selectedSwitchIndex
property to switch index which is toggled and reload your table view.
@objc func switchChanged(_ sender: UISwitch!){
// you would want to save the index only when its set to on
guard sender.isOn else {
// setting the selectedSwitchIndex to nil if the switch is turned off
selectedSwitchIndex = nil
return
}
selectedSwitchIndex = sender.tag
tableView.reloadData()
}
Switch Statement on didSelectRowAt Function in Swift
try my code
var count = 0
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
count += 1
let cell = tableView.cellForRow(at: indexPath)
switch count {
case 1:
cell.cellLabel.text = "first time label changes"
case 2:
cell.cellLabel.text = "second time label changes"
default:
cell.cellLabel.text = "change the label"
}
}
if you need "first" when you touch it 3 times
var count = 0
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
count += 1
if count > 2 {
count = 1
}
let cell = tableView.cellForRow(at: indexPath)
switch count {
case 1:
cell.cellLabel.text = "first time label changes"
case 2:
cell.cellLabel.text = "second time label changes"
default:
cell.cellLabel.text = "change the label"
}
}
How can i hide a Section when UISwitch is Changed
Try to change your code this way, Add one action with your UISwitch
ValueChanged
event and reload the tableView
.
@IBAction func switchValueChange(sender: UISwitch) {
tableView.reloadData()
}
Now change your UITableViewDataSource
method like this way
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
if mySwitch.on {
return 3
}
else {
return 2
}
}
// set number for rows for each setion
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 {
return self.going.count
}
if section == 1 {
if mySwitch.on {
return self.eventdays.count
}
else {
return self.others.count
}
}
if section == 2 {
return self.others.count
}
return 0
}
func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if section == 0 {
return "Can Go?"
}
if section == 1 {
if mySwitch.on {
return "Days"
}
else {
return "Others"
}
}
if section == 2 {
return "Others"
}
return "Default Title"
}
What is the index path of a table view cell that is currently being rearranged (moved) by the user?
- (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath: (NSIndexPath *)proposedDestinationIndexPath
{
if (proposedDestinationIndexPath.section != sourceIndexPath.section)
{
return sourceIndexPath;
}
return proposedDestinationIndexPath;
}
Do not forget to do another check in your tableView:moveRowAtIndexPath:toIndexPath: data source method as shown below, you do not want to run your application logic when the destination is similar to the source.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
{
if(sourceIndexPath == destinationIndexPath)
{
return;
}
//application logic
}
Related Topics
Open Links in Safari Instead of Uiwebview
Create Singleton of a Viewcontroller in Swift 3
Changing Uitableview's Section Header/Footer Title Without Reloading the Whole Table View
How to Make Nsurlsession Post Request in Swift
The Sandbox Is Not in Sync with the Podfile.Lock-Ios
How to Send Email Using Mfmailcomposeviewcontroller in Simulator
Cannot Assign to Property in Protocol - Swift Compiler Error
How to Install iOS 7.0 and iOS 8.0 Simulators in Xcode 6.1
How to Get the Front Camera in Swift
Path Extension and Mime Type of File in Swift
Can't Load Uiviewcontroller Xib File in Storyboard in Swift
Does Webkit in iOS 11 (Beta) Support Webrtc
Constant Movement in Spritekit
How to Find the Address of a Stack Trace in Lldb for iOS
Could Not Cast Value of Type 'Uitableviewcell' to '(Appname).(Customcellname)'