Populate Number of rows in section from CoreData w

2019-07-19 10:26发布

In my CoreData, I have a Person entity, and each Person can have multiple (to Many) Statement entities. The statement entity has an attribute called amountOwed which is a decimal amount. Right now my idea is to loop over all the amounts and add them up, if they of a positive amount add them to the positive array and if they are negative amount add them to that array. Then use that array to figure out how many cells each sections needs to display.

I created a fetchedResultsController and I am trying to use that for the for loop

for i in 0..<fetchedResultsController.fetchedObjects!.count {

        let person = fetchedResultsController.fetchedObjects?[i]

        let amountTotal = person?.value(forKeyPath: "statement.@sum.amountOwed") as? Decimal

        if(amountTotal! <= Decimal(0) )
        {
            postiveCellNumber += 1
            print("\(postiveCellNumber) postive number count")
        }
        else{
            negativeCellNumber += 1
            print("\(negativeCellNumber) negative number count")
        }

    }

Then, I'm trying to use those arrays in the numberOfRowsInSection function like so:

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

    switch(section) {
    case 0:
        return postiveCellNumber
    case 1:
        return negativeCellNumber

    default :return 0
    }
}

I don't think my for loop is looping properly as I get an error that says

no object at index 2 in section at index 0.

2条回答
\"骚年 ilove
2楼-- · 2019-07-19 10:43

It's very difficult to identify the specific cause of the error, without seeing more of how your FRC and tableView are constructed. But this bit looks suspicious:

    if(amountTotal! <= Decimal(0) )
    {
        postiveCellNumber += 1
        print("\(postiveCellNumber) postive number count")
    }

Surely the if condition is back to front: you should increment the positiveCellNumber if amountTotal! >= Decimal(0)?

But that aside, even if you successfully calculate the counts, you will then face the issue of working out which of the FRC's fetchedObjects should appear in each row of each section:

  • You could do this "on the fly" in cellForRowAt, but that will involve iterating through the fetchedObjects again, to determine which appear in which section, which is clumsy and inefficient.
  • You could separate the fetchedObjects out into two separate arrays as a one-off step, once the FRC has done its performFetch. But you then need pretty ugly FRC delegate methods to update the two arrays whenever the FRC's fetchedObjects array is updated.
  • You could configure your FRC to automatically assign its fetched objects to the correct section, by specifying a sectionNameKeyPath and associated sort descriptors for the underlying fetch. The problem here is that it is not possible to sort the fetch using a calculated figure. If you want to pursue this route, you will need to add a totalAmountOwed attribute to your Person entity, and to ensure it is updated whenever the related Statements change.
  • Alternatively, you could follow @HalMueller's suggestion, and use two separate FRCs. You would use complementary predicates for the underlying fetches, one to get only those Persons with positive amount owed, the other to get those with negative amount owed. You can then use the fetchedObjects array for one FRC to populate section 0, and the other FRC to populate section 1. Overall, I think this is the solution I would recommend.
查看更多
Lonely孤独者°
3楼-- · 2019-07-19 10:46

How about using two different queries, one for the positive values and one for the negative ones, with two different fetched results controllers? Then you can let the FRC do the iterating and counting for you.

You won't be able to use the FRCs to manage sections. You'll have to do that yourself. Specify nil for the sectionNameKeyPath. Then you want something like

func numberOfSections(in tableView: UITableView) -> Int {
    return 2
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if section == 0 {
        return positiveResultsController.fetchedObjects?.count ?? 0
    }
    else {
        return negativeResultsController.fetchedObjects?.count ?? 0
    }
}

or maybe

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if section == 0 {
        let sectionInfo = positiveResultsController.sections![section]
        return sectionInfo.numberOfObjects
    }
    else {
        let sectionInfo = negativeResultsController.sections![section]
        return sectionInfo.numberOfObjects
    }
}

with similar logic for tableView(_:cellForRowAt:).

查看更多
登录 后发表回答