Blue Moose
Blue Moose

Reputation: 125

Adding the sum of labels from a table cell in Swift

I cannot figure this out since I do not know enough about table cells. I am building an invoice app for myself. In my tableview custom cell I made a label on the right side that is for amount due. when you fill out the invoice it prints out the amount in that label.

I have an empty label at the very top call totalDue that I want to have the sum of every amount in the table. I am struggling with this.

What I have is

import UIKit

var clientName = [String]()
var dueDate = [String]()
var projecDescript = [String]()
var dateStamp = Date()
var invoiceNum = [String]()
var amountDue = [String]()

var clientPicker = [""]





// Custom cell to make all input fields custom
class CustomCell: UITableViewCell {
    //Make your outlets here, connect the outlets from cell in your storyboard

    @IBOutlet var clientNameLabel: UILabel!
    @IBOutlet var descriptionLabel: UILabel!
    @IBOutlet var dateLabel: UILabel!
    @IBOutlet var amountLabel: UILabel!
    @IBOutlet var invoiceNum: UILabel!
    @IBOutlet var dateStamp: UILabel!

}

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet var clientTableList: UITableView!
    @IBOutlet var totalDue: UILabel!
    @IBOutlet var totalBillsLabel: UILabel!


    func calculateSum() {
    var sum = 0

    for amount in amountDue {
    sum += amount
    }

    totalDue.text = "\(sum)"

    }


    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        return (clientName.count)
        return (dueDate.count)
        return (projecDescript.count)
        return (invoiceNum.count)
        return (amountDue.count)

    }



    // This is the new items added into the inputs
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
    {
        let cell = tableView.dequeueReusableCell(withIdentifier: "clientCell", for: indexPath) as! CustomCell

        // Adds Clients Name
        let companyName = clientName[indexPath.row]
        cell.clientNameLabel?.text = companyName

        // Adds Clients Description
        let descriptionName = projecDescript[indexPath.row]
        cell.descriptionLabel?.text = descriptionName

        // Adds the amount due
        let amountName = amountDue[indexPath.row]
        cell.amountLabel?.text = "$\(amountName)"

        //Adds the total number of bills that you have in invoice
        totalBillsLabel.text = "\(indexPath.row + 1)"

        //Adding sum of all bills
        sum += Int((amountName as NSString).floatValue)
        //sum = Int((amountName as NSString).floatValue)

        totalDue.text = "\(sum)"

        //Adds DueDate
        let invoiceDate = "Due \(dueDate[indexPath.row])"
        cell.dateLabel?.text = invoiceDate

        //Adds invoice Number
        let invoiceNum = "Invoice #BMCS \(indexPath.row + 1)"
        cell.invoiceNum.text = invoiceNum

        //TimeStamp in the label datestamp
        let timeStamp = "\(DateFormatter.localizedString(from: Date(), dateStyle: .short, timeStyle: .short))"
        cell.dateStamp?.text = timeStamp

        return cell
    }


    func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
        let editAction = UITableViewRowAction(style: .default, title: "Edit") { (action, index) in

            //tableView.isEditing = true


            DispatchQueue.main.async() {
                self.performSegue(withIdentifier: "EditDetails", sender: self)
            }


            print("Edit Button Pressed")
        }

        editAction.backgroundColor = UIColor.green

        let deleteAction = UITableViewRowAction(style: .destructive, title: "Remove") { (action, indexPath) in
            //Remove the labels in the custom cell
            clientName.remove(at: indexPath.row)
            //dueDate.remove(at: indexPath.row)
            projecDescript.remove(at: indexPath.row)

            amountDue.remove(at: indexPath.row)
            tableView.deleteRows(at: [indexPath], with: .fade)

            //minus one total bill when deleting one
            self.totalBillsLabel.text = "\(indexPath.row - 1)"
            if indexPath.row == 0 {
                self.totalBillsLabel.text = "0"
            }



            self.clientTableList.reloadData()

        }

        let emailAction = UITableViewRowAction(style: .default, title: "Email") { (action, index) in
            print("Email Button Pressed")
        }

        emailAction.backgroundColor = UIColor.orange

        let phoneCallAction = UITableViewRowAction(style: .default, title: "Call") { (action, index) in
            print("Call Button Pressed")
        }

        phoneCallAction.backgroundColor = UIColor.blue



        return [deleteAction,editAction,emailAction,phoneCallAction]
    }

    func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
        return true
    }


    override func viewDidAppear(_ animated: Bool) {
        clientTableList.reloadData()

    }




    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

Second controller

@IBAction func addInvoice(_ sender: Any) {


        if clientNameInput.text != "" && descriptionNameInput.text != ""  && amountInput.text != ""
        {
            clientName.append(clientNameInput.text!)
            //clientInput.text = ""

            projecDescript.append(descriptionNameInput.text!)
            //descriptionFieldInput.text = ""

            //dueDate.append(dateInput.text!)
            //dateInput.text = ""

            amountDue.append(amountInput.text!)
            //amountList.text = ""

            dueDate.append(newDueDateLabel.text!)


            // After hit send this is the button that takes you back without having to back out yourself
            _ = navigationController?.popViewController(animated: true)
        }

    }

Upvotes: 0

Views: 2180

Answers (2)

3stud1ant3
3stud1ant3

Reputation: 3606

Please add this

var clientName = [String]()
var dueDate = [String]()
var projecDescript = [String]()
var dateStamp = Date()
var invoiceNum = [String]()
var amountDue = [String]()
var sum = 0.0

remove sum from other places in your viewcontroller

then in your second view controller

after amountDue.append(amountInput.text!)

add this

sum += Double(amountInput.text!)!

then in your ViewController

add this

override func viewDidAppear(_ animated: Bool) {
                super.viewDidAppear(animated)
                totalDue.text = "\(sum)"
}

Upvotes: 0

kwdev
kwdev

Reputation: 116

Do not compute the total in cellForRowAt. That is called every time the row is made visible on the screen, so even if it were summing everything, it would be wrong. Create a separate function that computes the sum and return that to populate the label. Something like:

func calculateSum() {
    var sum = 0

    for amount in amountDue {
        sum+= Int(amount) // more practical to convert to float here
    }

    totalDue.text = "\(sum)"
}

Then call this method in your viewDidLoad and other appropriate places, such as after a new row is added.

Upvotes: 1

Related Questions