Unable to Save On/Off State of a Uitableviewcell

unable to save on/off state of a UITableViewCell?

In Swift the most efficient way is a callback closure.

In the cell add a property callback with a closure passing a Bool value and no return value. Call the callback when the value of the switch changed.

class TableViewCell: UITableViewCell {

@IBOutlet weak var timeLbl: UILabel!
@IBOutlet weak var switchBtn: UISwitch!

var alarm = Bool()

var callback : ((Bool) -> Void)?

@IBAction func valChange(_ sender: UISwitch) {
callback?(sender.isOn)
}
}

In cellForRow in the controller add the callback, in the closure update the model.

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath) as! TableViewCell

let item = items[indexPath.row]
cell.timeLbl.text = item.time
cell.switchBtn.isOn = item.isOn

cell.callback = { newValue in
self.items[indexPath.row].isOn = newValue
}

return cell
}

If cells can be inserted, deleted or moved you have to pass also the cell to get the actual index path

class TableViewCell: UITableViewCell {

@IBOutlet weak var timeLbl: UILabel!
@IBOutlet weak var switchBtn: UISwitch!

var alarm = Bool()

var callback : ((UITableViewCell, Bool) -> Void)?

@IBAction func valChange(_ sender: UISwitch) {
callback?(self, sender.isOn)
}
}

and

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath) as! TableViewCell

let item = items[indexPath.row]
cell.timeLbl.text = item.time
cell.switchBtn.isOn = item.isOn

cell.callback = { currentCell, newValue in
let currentIndexPath = tableView.indexPath(for: currentCell)!
self.items[currentIndexPath.row].isOn = newValue
}

return cell
}

How to save the state of UITableViewCell accessory checkmark in Swift 3

Create a class variable of type IndexPath. In your cellForRowAt method set .checkmark accessory type only if index path matches the class variable and .none otherwise. In didSelectRowAt method update the indexPath of selected variable and just reload the tableview

UISwitch in custom UITableViewCell Reuse Issue

I would recommend to you create cellViewModel class and keep array of it instead of just string. You cellViewModel may look like,

class CellViewModel {
let title: String
var isOn: Bool

init(withText text: String, isOn: Bool = false /* you can keep is at by default false*/) {
self.title = text
self.isOn = isOn
}

Now, build array of CellViewModel

let array =["One","Two","Three","Four","Five","Six","Seven","Eight","Nine","Ten"]
var cellViewModels = [CellViewModel]()
for text in array {
let cellViewModel = CellViewModel(withText: text)
cellViewModels.append(cellViewModel)
}

Change your tableVieDelegate function to :

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CustomTableViewCell
let cellViewModel = cellViewModels[indexPath.row]
cell.label.text = cellViewModel.title
cell.toggleSwitch.isOn = cellViewModel.isOn
cell.delegate = self
return cell
}

In you Custom Cell class, add this protocol :

protocol CellActionDelegate: class {
func didChangeSwitchStateOnCell(_ cell: CustomTableViewCell)
}

Add delegate as property in your custom cell,

weak var delegate: CellActionDelegate?

Also, on switch change, add this line,

delegate?.didChangeSwitchStateOnCell(self)

Now, your viewController should register and listen to this delegate :
I have added line cellForRowAtIndexPath to register for delegates. To listen this delegate, add this function in your VC.

func didChangeSwitchStateOnCell(_ cell: CustomTableViewCell) {
let indexPath = tableView.indexPath(for: cell)
cellViewModels[indexPath.row].isOn = cell.toggleSwitch.isOn
}

How to retrieve UISwitch state in each of my UITableView cells?

You save that value just like any other value you use in a table view -- in an array that's your data source. Given what you show in your image, your data source should be an array of dictionaries with keys for the menu item, price, and switch state. In cellForRowAtIndexPath, you would set the state of the switch based on the value ( a BOOL) in your array.

UITableViewCell subview disappears when cell is selected

UITableViewCell changes the background color of all sub views when cell is selected or highlighted ,You can Solve this problem by overriding Tableview cell's setSelected:animated and setHighlighted:animated and resetting view background color.

In Objective C :

- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
UIColor *color = self.yourView.backgroundColor;
[super setSelected:selected animated:animated];

if (selected){
self.yourView.backgroundColor = color;
}
}

-(void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated{
UIColor *color = self.yourView.backgroundColor;
[super setHighlighted:highlighted animated:animated];

if (highlighted){
self.yourView.backgroundColor = color;
}
}

In Swift 3.1 :

override func setSelected(_ selected: Bool, animated: Bool) {
let color = yourView.backgroundColor
super.setSelected(selected, animated: animated)

if selected {
yourView.backgroundColor = color
}
}

override func setHighlighted(_ highlighted: Bool, animated: Bool) {
let color = yourView.backgroundColor
super.setHighlighted(highlighted, animated: animated)

if highlighted {
yourView.backgroundColor = color
}
}

Is it possible to prevent uitableviewcell to unload on device rotation?

I think you cannot prevent reusing. You can reuse cell's smart (for example, save cell's content before rotation / restore after rotation). For right positioning:

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)io
{
[self saveContentOfCells:[self.tableView indexPathsOfVisibleCells]];
self.lastVisible = [[self.tableView indexPathsOfVisibleCells] lastObject];
}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)io
{
[self.tableView scrollToRowAtIndexPath:self.lastVisible atScrollPosition:UITableViewScrollPositionBottom];
}

- (UITableViewCell*)tableView:(UITableView*)tv cellForRowAtIndexPath:(NSIndexPath*)ip
{
// dequeue cell
// try to restore content if any, clear restoration info
// if no restoration info setup cell
// return cell
}


Related Topics



Leave a reply



Submit