使用NSFetchedResultsController如何以编程方式设置5个部分以显示并过滤它们以获取适当的行

时间:2016-05-29 20:51:56

标签: swift core-data filter nsfetchedresultscontroller nsfetchrequest

重新迭代这里是我的困境,我正在重构我的代码以使用NSFetchedResultsController,我希望硬编码一组5个部分,我想在任何时候都显示它们,无论它们中是否有任何行或者不。我有点成功地让他们出现,但不幸的是我无法在正确的部分下显示相应的行。 (注意:我正在使用带有按钮的自定义标头,只要用户想要将单元格添加到任何特定部分,就会添加行。)coreData中的模型关系是Dog模型可以有许多Task但是Task只能有一只狗。不幸的是,我似乎正在为我创建的每个独特的“狗”获取所有任务,因此它们都具有相同的信息。

这是我的Task模型和我用来在NSFetchedResultsController中创建5个部分的枚举。

import Foundation
import CoreData

enum Type: String {
    case Meals = "Meals"
    case Exercise = "Exercise"
    case Health = "Health"
    case Training = "Training"
    case Misc = "Misc"
}


class Task: NSManagedObject {
    static let kClassName = "Task"

    convenience init?(title: String, type: Type, isComplete: Bool, context: NSManagedObjectContext = Stack.sharedStack.managedObjectContext) {
        guard let entity = NSEntityDescription.entityForName(Task.kClassName, inManagedObjectContext: context) else { return nil }

        self.init(entity: entity, insertIntoManagedObjectContext: context)
        self.title = title
        self.isChecked = isComplete
        self.type = type.rawValue
    }
}

这是我的FetchedResultsController,我将Enum Type作为sectionNameKeyPath传递。

class TaskController {
    static let sharedController = TaskController()
    private let kTask = "Task"
    var fetchedResultsController: NSFetchedResultsController

    var dog: Dog?

    init() {
        let request = NSFetchRequest(entityName: kTask)
        let sortDescriptor1 = NSSortDescriptor(key: "type", ascending: true)
        request.sortDescriptors = [sortDescriptor1]

        fetchedResultsController = NSFetchedResultsController(fetchRequest: request, managedObjectContext: Stack.sharedStack.managedObjectContext, sectionNameKeyPath: String(Type), cacheName: nil)
        _ = try? fetchedResultsController.performFetch()
    }
}

在numberOfRowsInSection中,我试图将sections.count匹配为等于函数属性部分的部分,因为我假设fetchedResultsController部分在第一次创建行之前实际上并不存在?说实话,我现在迷路了,因为我不知道如何获取正确的行以匹配相应的部分。在我决定重构代码并将其更新为NSFetchedResultsController方式之前,评论代码是我最初检索正确部分的正确行的方式。

extension DogDetailViewController: UITableViewDataSource {
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        guard let sections = TaskController.sharedController.fetchedResultsController.sections else { return 0 }

        if sections.count > 0 && section < sections.count {
            return sections[section].numberOfObjects
        }
        return 0

            //            }

            //        if let dog = self.dog {
            //            switch section {
            //            case 0:
            //                return dog.tasks.filter({$0.type == String(Type.Meals)}).count
            //            case 1:
            //                return dog.tasks.filter({$0.type == String(Type.Exercise)}).count
            //            case 2:
            //                return dog.tasks.filter({$0.type == String(Type.Health)}).count
            //            case 3:
            //                return dog.tasks.filter({$0.type == String(Type.Training)}).count
            //            case 4:
            //                return dog.tasks.filter({$0.type == String(Type.Misc)}).count
            //            default:
            //                return 0
            //            }
            //        } else {
            //            return 0
            //        }
        }

感谢任何帮助,谢谢!

1 个答案:

答案 0 :(得分:1)

如果您希望显示所有5个部分,无论给定的狗存在多少个该类型的任务,您可以考虑对部分的数量及其顺序进行硬编码并使用NSFetchedResultsController(因此每个部分都有不同的NSFetchRequest

您现有的提取请求不会将您的请求限制在特定的狗身上(您可以通过创建具有适当约束的NSPredicate并在提取请求中设置它来执行此操作。这可能很重要,因此您不要将每个Task拉入内存然后执行过滤器。这将要求您的Task实体与您的数据模型中的Dog实体有关系,根据您发布的代码,这种关系并不明显。我会假设你有这种关系。您也不能以现在的方式为TaskController(下面的TaskDataSource)使用单例模型,因为每次更改{{1}时都必须创建一个新模型你想提出请求。

另请注意,我只是继续Dog进入TaskController并直接采用TaskDataSource协议。这不是必需的,但如果您的应用可能希望在多个屏幕上显示此内容,则可能会更有效。

UICollectionViewDataSource