Reputation: 125
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
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
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