我是否应该使用CoreData谓词来填充我的UITableview?

时间:2016-02-05 19:26:18

标签: xcode swift uitableview core-data nspredicate

我有一个旧的应用程序,我使用CoreData和Swift 2重建。这是我第一次去Coredata,所以我确定我没有尽可能以最有效的方式做所有事情。例如,我在Coredata中有2个实体,一个Person实体和一个Statement实体。个人实体与许多人的关系是"对于Statement实体,Statement实体与" To One"到Person实体。所以基本上我的Person对象可以有多个Statement对象。这一切都正常,我能够成功地将它们添加到CoreData中。

接下来我有一个UIViewController,里面有一个UITableView。我将tableview的选择下拉菜单设置为Multiple Sections。我为表格视图分配了2个部分。

当我获取CoreData实体时,我将它们放入一个数组中,以便我能够使用该数组并填充tableview。

 var persons: [Person]!
 persons = try coreDataStack.context.executeFetchRequest(fetchRequest) as! [Person]

之后(我认为这是事情可以简化的地方)我将该数组分成2个不同的数组,以便Table视图中的每个Section都拥有它自己的数据源。我认为这是我可以使用CoreData NSPredicate的地方,但在查看了一些教程并阅读了我在Coredata上的一本书的几章后,我仍然不太了解如何使用它们。所以这就是我从Coredata创建的数组中制作2个不同数组的过程。

for(var i = 0; persons?.count > i; i++){
        newNumber = 0.00
        print("\(persons?[i].statements?.count) this is the statements count")

        if(persons?[i].statements?.count > 0){

            print("YES statements")
            //persons[i].statements
            for(var x = 0; persons[i].statements?.count > x; x++){

                //print( "\(persons[i].statements?[x].name) this is the name " )
                let statementNumber = persons[i].statements?[x] as? Statement
                //print(statementNumber?.amount)

                newNumber = newNumber + Double((statementNumber?.amount)!)
                //print(newNumber)
            }
            // check the new number and see if it's positive or negative
            if(newNumber >= 0){
                positiveeArray.append(persons[i])
                //print("\(positiveArray.count) This is the count of the posve array")
            }
            else{
                negativeArray.append(persons[i])
                //print("\(negativeArray.count) This is the count of the negative array")
            }

        }else{

            print("there are no statements add this person to the positive array")
            positiveArray.append(persons[i])
        }
    }

基本上每个Statement实体都有一个金额属性。我想查看该属性是正数还是负数。这个系统再次起作用,但是看起来很难跳过来访问这些数据。

在此之后,我采用这两个数组(正面和负面)并使用它们来填充我的UITableView的不同部分。

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCellWithIdentifier("personCell", forIndexPath: indexPath) as! PersonTableViewCell

    //print("\(persons?[indexPath.row].statements?.count) this is the count to use")
    //print("\(indexPath.row) this is the index row")

    var numberForDispay = 0.00

    switch(indexPath.section) {
    case 0:
        if(positiveArray[indexPath.row].statements?.count != 0){

            for(var i = 0; positiveArray[indexPath.row].statements?.count > i; i++){

                let statementNumber = positiveArray[indexPath.row].statements?[i] as? Statement
                //print(statementNumber?.amount)
                numberForDispay = numberForDispay + Double((statementNumber?.amount)!)

                // this will make negative numbers positive
                numberForDispay = fabs(numberForDispay)

                let formatter = NSNumberFormatter()
                formatter.numberStyle = .CurrencyStyle

                cell.statementAmount.text = formatter.stringFromNumber(numberForDispay)
                //print("\(formatter) this is the number to use")
            }
        }else{
            cell.statementAmount.text = "$0.00"
        }
    case 1:
        if(negativeArray[indexPath.row].statements?.count != 0){

            for(var i = 0; negativeArray[indexPath.row].statements?.count > i; i++){

                let statementNumber = negativeArray[indexPath.row].statements?[i] as? Statement
                //print(statementNumber?.amount)
                numberForDispay = numberForDispay + Double((statementNumber?.amount)!)

                // this will make negative numbers positive
                numberForDispay = fabs(numberForDispay)

                let formatter = NSNumberFormatter()
                formatter.numberStyle = .CurrencyStyle

                cell.statementAmount.text = formatter.stringFromNumber(numberForDispay)
                //print("\(formatter) this is the number to use")
            }
        }else{
            cell.statementAmount.text = "$0.00"
        }
    default: ""
    }

    switch(indexPath.section) {
        case 0:
            cell.personName.text = postitiveArray[indexPath.row].name
            cell.backgroundColor = Styles.blueColor();
        case 1:
            cell.personName.text = negativeArray[indexPath.row].name
            cell.backgroundColor = Styles.redColor();

        default: cell.personName.text = "hello"
    }

    cell.personName.textColor = Styles.whiteColor()
    cell.statementAmount.textColor = Styles.whiteColor()

    // will make the divide line full width
    cell.separatorInset = UIEdgeInsetsMake(0, 0, cell.frame.size.width, 0)
    if (cell.respondsToSelector("preservesSuperviewLayoutMargins")){
        cell.layoutMargins = UIEdgeInsetsZero
        cell.preservesSuperviewLayoutMargins = false
    }

    // set the accessory icon color
    cell.tintColor = UIColor.whiteColor()

    return cell
}

这再次起作用,但我希望我能够清理我拥有的代码量并简化此过程。我来自flash / AS3背景。我知道这是一个很长的帖子,所以如果你走到这一步,谢谢!我只想确保在处理这些应用时,我没有为自己创造更多的工作。

1 个答案:

答案 0 :(得分:2)

我建议使用NSFetchedResultsController。你甚至可以使用两个,每个部分一个。您可以在内存,数据库访问和性能方面进行大量优化。

以下是2个谓词,您将其添加到获取的结果控制器的获取请求中(获取Statement个对象):

NSPredicate(format: "amount < 0")
NSPredicate(format: "amount >= 0")

2作为部分的数量返回,将相应的抓取结果控制器的fetchedObjects.count作为numberOfRowsInSection

您也可以使用单个获取的结果控制器执行此操作。但是你必须在数据库中硬编码一个标志,指示每个数量属于哪个部分。因此,无论何时设置金额,您都会自动将实体对象设置为加号/减号标志。

顺便说一句,不是迭代项目,你可以在Swift中更简洁(不仅是托管对象,还有任何类型的对象)。 E.g。

let negative = allStatements.filter { $0.amount < 0 }
let positive = allStatements.filter { $0.amount >= 0 }

请注意,Core Data也有可用的聚合函数。一个人的所有陈述金额的总和将是

let sum = person.valueForKeyPath("@sum.amount") as! NSNumber

使用此技术,您可以拥有sum属性Person,只要您设置Statement的数量,该属性就会更新。

所以你的Person谓词就是

NSPredicate(format: "sum < 0")
NSPredicate(format: "sum >= 0")