我有一个旧的应用程序,我使用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背景。我知道这是一个很长的帖子,所以如果你走到这一步,谢谢!我只想确保在处理这些应用时,我没有为自己创造更多的工作。
答案 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")