bogdan barbulescu bogdan barbulescu - 4 months ago 10
Swift Question

Select row once and perform calculation swift

I have table view which displays a list of items and every time a row is selected, a checkmark is added and certain amount is added to

var total
.

If another row is selected it executes same behaviour as above and the previous amount for the deselected row is subtracted. Also the deselected row receives no checkmark.

The problem is that if a row is selected several times, it will keep adding the amount corresponding to the row selected.

What I want is to add the amount corresponding to the row only once regardless of how many times the row is selected.

class EighthViewController: UIViewController, UITableViewDelegate,UITableViewDataSource {

var total = 0

struct Item {
var name:String // name of the row
var selected:Bool // whether is selected or not
}

var frequency = [

Item(name:"Every week",selected: false),
Item(name:"Every 2 weeks",selected: false),
Item(name:"Every 4 weeks",selected: false),
Item(name:"Once",selected: false),
Item(name:"End of tenancy cleaning", selected: false)
]

@IBOutlet weak var tableView: UITableView!

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


func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return frequency.count
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}

// configure the cell
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath)
-> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell")
cell?.textLabel?.text = frequency[indexPath.row].name
return cell!
}

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.cellForRowAtIndexPath(indexPath)?.accessoryType = .Checkmark

if indexPath.row == 0 {
self.total += 30
print(total)

} else if indexPath.row == 1 {
self.total += 30
print(total)

} else if indexPath.row == 2 {
self.total += 30
print(total)

} else if indexPath.row == 3 {
self.total += 40
print(total)

} else if indexPath.row == 4 {
self.total += 44
print(total)
}
}

func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
tableView.cellForRowAtIndexPath(indexPath)?.accessoryType = .None

if indexPath.row == 0 {
self.total -= 30
print(total)

} else if indexPath.row == 1 {
self.total -= 30 // delete previous amount
print(total)


} else if indexPath.row == 2 {
self.total -= 30 // delete previous amount
print(total)


} else if indexPath.row == 3 {
self.total -= 40 // delete previous amount
print(total)

} else if indexPath.row == 4 {
self.total -= 44 // delete previous amount
print(total)
}

}
}

Answer

You've created an struct with the a bool property selected so you can use it very easy to avoid the amount in the cell is added several times, and you don't need to use the didDeselectRowAtIndexPath at all, to be notified every time a cell is tapped you need to use only didSelectRowAtIndexPath method like in the following way:

But for a better use of your struct I recommend introduce the amount inside the type and the code would be more clean like in this way:

struct Item {
  var name:String // name of the row
  var selected:Bool // whether is selected or not
  var amount: Int // value of the item
}

var frequency = [

   Item(name:"Every week",selected: false, amount: 30),
   Item(name:"Every 2 weeks",selected: false, amount: 30),
   Item(name:"Every 4 weeks",selected: false, , amount: 30),
   Item(name:"Once",selected: false, amount: 40),
   Item(name:"End of tenancy cleaning", selected: false, amount: 44)
]

And we need to save the last cell tapped for every time we want to to update the new one so wee need to create a optional property like this one:

var indexPathForCellSelected: NSIndexPath?

And then the code should be like the following:

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

    if !frequency[indexPath.row].selected {

        // this avoid set initial value for the first time
        if let index = indexPathForCellSelected {
            // clear the previous cell
            frequency[index.row].selected = false
            tableView.cellForRowAtIndexPath(index)?.accessoryType = .None
            self.total -= frequency[index.row].amount
        }

        // mark the new one
        frequency[indexPath.row].selected = true
        tableView.cellForRowAtIndexPath(indexPath)?.accessoryType = .Checkmark

        indexPathForCellSelected = indexPath
        self.total += frequency[indexPath.row].amount
    }
}

I hope this help you.