0

I'm a new developer and I have a finance app with a collection view of categories.

When the user taps on a category, the next page should populate a collection view of subcategories for the main category.

Here is my current data model:

import UIKit

struct Category {
    
    var name: String
    var color: UIColor
    var amountBudgeted: Double
    var subCategories: [SubCategory]
    
}

struct SubCategory {
    var name: String
    var amountBudgeted: Double
}

let categories = [
    Category(
        name: "Income",
        color: UIColor(rgb: Constants.green),
        amountBudgeted: 0.00,
        subCategories: [
            SubCategory(name: "Paycheck", amountBudgeted: 0.00),
            SubCategory(name: "Bonus", amountBudgeted: 0.00),
            SubCategory(name: "Dividend", amountBudgeted: 0.00),
            SubCategory(name: "Rental Income", amountBudgeted: 0.00),
    ]),
    Category(
        name: "Housing",
        color: UIColor(rgb: Constants.grey),
        amountBudgeted: 0.00,
        subCategories: [
            SubCategory(name: "Mortgage", amountBudgeted: 0.00),
            SubCategory(name: "Property Tax", amountBudgeted: 0.00),
            SubCategory(name: "HOA Fees", amountBudgeted: 0.00),
            SubCategory(name: "Household Repairs", amountBudgeted: 0.00),
    ]),
    Category(
        name: "Transportation",
        color: UIColor(rgb: Constants.red),
        amountBudgeted: 0.00,
        subCategories: [
            SubCategory(name: "Car Payment", amountBudgeted: 0.00),
            SubCategory(name: "Gas", amountBudgeted: 0.00),
            SubCategory(name: "Car Repairs", amountBudgeted: 0.00),
            SubCategory(name: "Registration", amountBudgeted: 0.00),
    ]),
    Category(
        name: "Food",
        color: UIColor(rgb: Constants.yellow),
        amountBudgeted: 0.00,
        subCategories: [
            SubCategory(name: "Groceries", amountBudgeted: 0.00),
            SubCategory(name: "Restaurants", amountBudgeted: 0.00),
    ]),
]

I can easily call the main category properties in cellForItemAt like cell.nameLabel.text = categories[indexPath.item].name, but I can't get the subcategory view to work.

I'm trying cell.nameLabel.text = categories[indexPath.item].subCategories[indexPath.item].name but that isn't working properly.

I also need to figure out how to relate the data between view controllers, but that might need to be a separate question.

Do I need to rethink my data model? Or do I need to set the cellForItemAt method differently?

Thanks.

BriScoLeg
  • 105
  • 1
  • 9
  • 1
    The problem is that when you click on the category you are not able to access the subcategory in the new view? – ERP Aug 04 '20 at 00:30
  • Yes, I don't know how to relate the data so that when the user taps on a category it populates the subcategory data. – BriScoLeg Aug 04 '20 at 00:53
  • 2
    I think your code should be working fine, there is no problem with you model definition whatsoever it seems perfectly fine, and so I am guessing that the error might be on how you are sending your data to the next view, you should make sure that the object that you are sending is populated and you have access to its fields – ERP Aug 04 '20 at 01:33
  • 1
    You should send the whole array of sub-categories, `subCategories`, to the next view controller and not just one. If you need info on how to pass data between view controllers see [this](https://stackoverflow.com/questions/5210535/passing-data-between-view-controllers) question – Joakim Danielson Aug 04 '20 at 07:15

1 Answers1

0

Here's how I was able to do it.

In the main category view controller:

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        
        if let vc = storyboard?.instantiateViewController(identifier: "SubVC") as? SubVC {
            
            vc.subCategories = categories[indexPath.item].subCategories
            navigationController?.pushViewController(vc, animated: true)

        }
    }

In the subcategory view controller:

    var subCategories: [SubCategory] = []

override func viewDidLoad() {
        super.viewDidLoad()
        
        collectionView.dataSource = self
        collectionView.delegate = self
    }

extension SubVC: UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return subCategories.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "SubCell", for: indexPath) as! SubCell
        
        cell.nameLabel.text = subCategories[indexPath.item].name
        cell.amountField.text = String(subCategories[indexPath.item].amountBudgeted)
        
        return cell
    }
    
}

Thanks to those who commented on this question.

Here is a video that also helped me with this: https://www.youtube.com/watch?v=dc5kLyAn6dg

I hope this helps a beginner like me in the future.

BriScoLeg
  • 105
  • 1
  • 9