How do I iterate through an array and display the contents of the array in a Table View? I have the table view all setup but when I write the for in loop it just displays contents in the first row.

How do I iterate through an array and display the contents of the array in a Table View?

I have the table view all setup but when I write the for in loop it just displays contents in the first row.

For example, I am making a loan calculator and I want the table view to display every months principal, interest, and balance all the way through the term of the loan like this:

1. P: $$$$$, I: $$$$$, Bal: $$$$$

2. P: $$$$$, I: $$$$$, Bal: $$$$$

3. P: $$$$$, I: $$$$$, Bal: $$$$$

4. P: $$$$$, I: $$$$$, Bal: $$$$$

5. P: $$$$$, I: $$$$$, Bal: $$$$$

I cannot get it to do this.

This is what I get:

60. P: $$$$$, I: $$$$$, Bal: $$$$$

Also, how do I get row 2 to calculate off of row 1 and row 3 to calculate off of row 2 and so forth.


Thank you

Answered by OOPer in 345169022

Your code is broken and I need to guess some parts, which makes hard to write a right answer. Also, your loan calculation seems to be broken...


But the reason you get only one row in your table view is clear enough.


In your line 56.

            data = ["\(paymentNumber). P: \(fResultPrincipal), I: \(fResultMonthlyInterest), Bal: \(fResultBalance)"]


Your whole `data` is replaced by a single-element Array `["\(paymentNumber)..."]`.


You may need to add another element for each iteration of your for-in statement, instead of replacing whole contents.

        data = []
        for _ in 1...intMonths {
            paymentNumber+=1
            
            //You may need to calculate fResultPrincipal, fResultMonthlyInterest and fResultBalance here.
            //...
            
            data += ["\(paymentNumber). P: \(fResultPrincipal), I: \(fResultMonthlyInterest), Bal: \(fResultBalance)"]
        }

You usually do not write for-in to show something in table view.

You may use for-in loop to set up your data model used as a data source for the table view.


Anyway, please show your code with all relevant parts.

This loop through is what is done by cellForRowAt.

if your data source is an array called data holding text:


    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
     
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
        cell.textLabel!.text = data[indexPath.row]

        return cell
    }


In your case, if you have define a strcut with principal, interest, and balance,

struct Line {

var principal: String // may be Float

var interest: String

var balance: String

}

var data : [Line]


and

cell.textLabel!.text = "P: \(data[indexPath.row].principal), I: \(data[indexPath.row].interest), Bal: \(data[indexPath.row].balancel)"



You must also set the number of sections and rows:


   override func numberOfSections(in tableView: UITableView) -> Int {

        return 1     // If only one section
    }
   
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
       
        return data.count
    }


Don't forget to declare the datasource and delegate

class ViewController: UIViewController, UITextFieldDelegate, UITableViewDelegate, UITableViewDataSource {
    
    var data: [String] = []
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return data.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        cell.textLabel?.text = data[indexPath.row]
        return cell
    }

let dblMONTHS_YEAR: Double = 12

var dblAPR: Double = 0
    var dblTotalAmount: Double = 0                 // To hold the vehicle total cost.
    var dblCost: Double = 0                        // To hold vehicle cost.
    var dblDownPayment: Double = 0                 // To hold down payment.
    var intMonths: Int = 0                         // To hold number of months for the loan.
    var dblLoan: Double = 0                        // To hold the amount of the loan.
    var dblMonthlyPayment: Double = 0              // To hold the monthly payment.
    var dblTotalInterest: Double = 0               // To hold the total interest.
    var dblTaxRate: Double = 0                     // To hold the tax rate.
    var dblTotalTax: Double = 0                    // To hold the total tax.
    var dblMonthlyRate: Double = 0
    
    var principal: Double = 0
    var monthlyInterestRate: Double = 0
    var balance: Double = 0
    var monthlyInterest: Double = 0
    var paymentNumber: Int = 0
    
    // Payment Structure Function
    func paymentStructure() {
        
        balance = dblLoan - principal
        monthlyInterestRate = ((dblAPR/100)/12)
        monthlyInterest = dblMonthlyRate * dblLoan
        principal = dblMonthlyPayment - monthlyInterest
        
        
        let fprincipal = NSNumber(value: principal)
        let fResultPrincipal = NumberFormatter.localizedString(from: fprincipal, number: .currency)
        
        let fBalance = NSNumber(value: balance)
        let fResultBalance = NumberFormatter.localizedString(from: fBalance, number: .currency)
        
        let fMonthlyInterest = NSNumber(value: monthlyInterest)
        let fResultMonthlyInterest = NumberFormatter.localizedString(from: fMonthlyInterest, number: .currency)
        
        for _ in 1...intMonths {
            paymentNumber+=1
            
        data = ["\(paymentNumber). P: \(fResultPrincipal), I: \(fResultMonthlyInterest), Bal: \(fResultBalance)"]
        }

        table.reloadData()
        }

@IBAction func btnCalculate(_ sender: UIButton) {

else if txtVehicleCost.text != nil && txtDownPayment.text != nil && txtNumberOfMonths.text != nil && txtAPR != nil && txtTaxRate.text != nil {
            
            dblCost = Double(txtVehicleCost.text!)!
            dblDownPayment = Double(txtDownPayment.text!)!
            intMonths = Int(txtNumberOfMonths.text!)!
            dblAPR = Double(txtAPR.text!)!
            dblTaxRate = Double(txtTaxRate.text!)!
            
            // Clear the message.
            lblMessage.text = ""
            
            // Get the tax rate.
            dblTaxRate = dblTaxRate / 100
            
            // Get the APR rate.
            dblAPR = dblAPR / 100
            
            // Get the monthly rate.
            dblMonthlyRate = dblAPR / dblMONTHS_YEAR
            
            // Get the amount of the loan.
            dblLoan = dblCost - dblDownPayment
            
            // Get the total tax.
            dblTotalTax = (dblLoan + dblDownPayment) * (dblTaxRate)
            
            // Get the monthly payment.
            dblMonthlyPayment = ((dblCost + dblTotalTax) - dblDownPayment) * (dblMonthlyRate / (1 - pow(1 + dblMonthlyRate, Double(-intMonths))))
            
            // Get the total interest.
            dblTotalInterest = dblMonthlyPayment * Double(intMonths) - dblLoan
            
            // Get the Total Amount.
            dblTotalAmount = dblCost + dblTotalInterest + dblTotalTax
            
            // Get the Vehicle Cost.
            dblCost = ((dblTotalAmount - dblTotalInterest) - dblTotalTax)
            
            // Format the results.
            let fMonthlyPayment = NSNumber(value: dblMonthlyPayment)
            let fResultMonthkyPayment = NumberFormatter.localizedString(from: fMonthlyPayment, number: .currency)
            
            let fTotalInterest = NSNumber(value: dblTotalInterest)
            let fResultTotalInterest = NumberFormatter.localizedString(from: fTotalInterest, number: .currency)
            
            let fTotalVehicleTax = NSNumber(value: dblTotalTax)
            let fResultTotalTax = NumberFormatter.localizedString(from: fTotalVehicleTax, number: .currency)
            
            let fTotalAmount = NSNumber(value: dblTotalAmount)
            let fResultTotalAmount = NumberFormatter.localizedString(from: fTotalAmount, number: .currency)
            
            // Print the Result labels.
            lblMonthlyPayment.text = fResultMonthkyPayment
            lblTotalInterest.text = fResultTotalInterest
            lblTotalTax.text = fResultTotalTax
            lblTotalAmount.text = fResultTotalAmount
            
            paymentStructure()
        }
    }

What am I doing wrong? It doesn't loop through to fill in the tableview for every month. Only one month shows and the payment number is the number of payments that the user selects. For example if the user selects 60 months then the table view looks like this:


60. Prin: $$$$$, Int: $$$$$, Bal: $$$$$

Accepted Answer

Your code is broken and I need to guess some parts, which makes hard to write a right answer. Also, your loan calculation seems to be broken...


But the reason you get only one row in your table view is clear enough.


In your line 56.

            data = ["\(paymentNumber). P: \(fResultPrincipal), I: \(fResultMonthlyInterest), Bal: \(fResultBalance)"]


Your whole `data` is replaced by a single-element Array `["\(paymentNumber)..."]`.


You may need to add another element for each iteration of your for-in statement, instead of replacing whole contents.

        data = []
        for _ in 1...intMonths {
            paymentNumber+=1
            
            //You may need to calculate fResultPrincipal, fResultMonthlyInterest and fResultBalance here.
            //...
            
            data += ["\(paymentNumber). P: \(fResultPrincipal), I: \(fResultMonthlyInterest), Bal: \(fResultBalance)"]
        }

Yes, it worked. I had data outside of the loop. Thank you!

I have another question for you.

The data array fills in the table but if the table is already filled and I want to make another selection in my app it just appends onto the table like this:


First time if the table is clear :


1. P: $$$$$, I: $$$$$, Bal: $$$$$

2. P: $$$$$, I: $$$$$, Bal: $$$$$

3. P: $$$$$, I: $$$$$, Bal: $$$$$

4. P: $$$$$, I: $$$$$, Bal: $$$$$

5. P: $$$$$, I: $$$$$, Bal: $$$$$


Second time if the table is not clear:


1. P: $$$$$, I: $$$$$, Bal: $$$$$

2. P: $$$$$, I: $$$$$, Bal: $$$$$

3. P: $$$$$, I: $$$$$, Bal: $$$$$

4. P: $$$$$, I: $$$$$, Bal: $$$$$

5. P: $$$$$, I: $$$$$, Bal: $$$$$

6. P: $$$$$, I: $$$$$, Bal: $$$$$

7. P: $$$$$, I: $$$$$, Bal: $$$$$

8. P: $$$$$, I: $$$$$, Bal: $$$$$

9. P: $$$$$, I: $$$$$, Bal: $$$$$

10. P: $$$$$, I: $$$$$, Bal: $$$$$


How do I get the table to clear automatically first before it runs the code so the table always starts with 1?

Also, I need help setting up the right formulas for principal, interest, and balance.

How do I get the formula to calculate off of the row before the current row in the table?


Thank you for your help!

How do I get the table to clear automatically first before it runs the code so the table always starts with 1?

Have you noticed the line in the code I have shown?

    data = []

Put that line where you want to clear the table. There's no automatically in programming. It's you to decide where to clear.


Also, I need help setting up the right formulas for principal, interest, and balance.

You have some formulas to calculate them. Try putting them to inside the for-in statement and see what happens.

Generally, your code uses many instance properties in a bad manner and they should be local variables.

Yes, thank you! It worked! I had to play with the code a little bit but I got it working right.

I put all of my variables inside my button clicked function and it seemed to work better.

I just need help with a few more things.

One thing I just noticed is that when I click on the calculate button, if I am already scrolled down in the table view then I have to scroll back up after the table view reloads.


1. How do I reload the table view from the top of the table view?


Thank you for your help!

If you mean you want to keep the position of scrolling, I do not have much experience about that, so there may be some better ways, but I would save the current scrolling position of the table view, reload it, and then restore the previous position.


You can use the property `contentOffset` or the method `setContentOffset(_:animated:)`.

How do I iterate through an array and display the contents of the array in a Table View? I have the table view all setup but when I write the for in loop it just displays contents in the first row.
 
 
Q