Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/116.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 如何在NSFetchedResultsController中构建子部分_Ios_Swift_Cocoa Touch_Core Data - Fatal编程技术网

Ios 如何在NSFetchedResultsController中构建子部分

Ios 如何在NSFetchedResultsController中构建子部分,ios,swift,cocoa-touch,core-data,Ios,Swift,Cocoa Touch,Core Data,我正在构建一个费用跟踪器,费用只能属于一个类别,但可以有多个标签s。这是我的对象图: 在我在表格视图中列出所有费用的屏幕中,我希望费用按日期分组(日期部分),然后按类别分组(或者,使用分段控件,按标记分组)。这是预期的用户界面: 我已经可以使用NSFetchedResultsController查询所有费用,按日期、然后按类别进行划分,但我无法获得(1)类别的总额和(2)其中的费用列表。我该怎么做呢?这是我当前的代码: let fetchedResultsController: NSFetc

我正在构建一个费用跟踪器,
费用
只能属于一个
类别
,但可以有多个
标签
s。这是我的对象图:

在我在表格视图中列出所有费用的屏幕中,我希望费用按日期分组(日期
部分),然后按类别分组(或者,使用分段控件,按标记分组)。这是预期的用户界面:

我已经可以使用
NSFetchedResultsController
查询所有费用,按日期、然后按类别进行划分,但我无法获得(1)类别的总额和(2)其中的费用列表。我该怎么做呢?这是我当前的代码:

let fetchedResultsController: NSFetchedResultsController<NSFetchRequestResult> = {
    let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Expense")
    fetchRequest.resultType = .dictionaryResultType

    fetchRequest.sortDescriptors = [
        NSSortDescriptor(key: #keyPath(Expense.sectionDate), ascending: false)
    ]

    fetchRequest.propertiesToFetch = [
        #keyPath(Expense.sectionDate),
        #keyPath(Expense.category)
    ]
    fetchRequest.propertiesToGroupBy = [
        #keyPath(Expense.sectionDate),
        #keyPath(Expense.category)
    ]

    let fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest,
                                                              managedObjectContext: Global.coreDataStack.viewContext,
                                                              sectionNameKeyPath: #keyPath(Expense.sectionDate),
                                                              cacheName: nil)
    return fetchedResultsController
}()
让fetchedResultsController:NSFetchedResultsController={
let fetchRequest=NSFetchRequest(entityName:“费用”)
fetchRequest.resultType=.dictionaryResultType
fetchRequest.sortDescriptors=[
NSSortDescriptor(键:#键路径(Expense.sectionDate),升序:false)
]
fetchRequest.propertiesToFetch=[
#密钥路径(费用。分段日期),
#关键路径(费用类别)
]
fetchRequest.propertiesToGroupBy=[
#密钥路径(费用。分段日期),
#关键路径(费用类别)
]
让fetchedResultsController=NSFetchedResultsController(fetchRequest:fetchRequest,
managedObjectContext:Global.coreDataStack.viewContext,
sectionNameKeyPath:#keyPath(Expense.sectionDate),
缓存名称:nil)
返回获取的ResultsController
}()

A应该预先警告我从未做过这件事,但就我个人而言,我会按如下方式着手:

  • 不要使用
    propertiesToGroupBy
    :它会强制您使用
    .dictionaryResultType
    ,这意味着您只能通过执行单独的获取来访问底层托管对象
  • 相反,将另一个计算属性添加到相关的NSManagedObject子类中,将
    sectionDate
    category.name
    组合在一起。此属性将用作FRC的
    sectionNameKeyPath
    ,以便FRC在tableView中为sectionDate和category name的每个唯一组合建立一个节
  • 添加
    category.name
    作为FRC底层获取的另一个排序描述符。这将确保FRC获取的
    费用
    对象的顺序正确(即,具有相同节日期和类别名称的所有
    费用
    对象放在一起)
  • 为每个节添加节标题视图。节的
    name
    属性(来自FRC)将包括节日期和类别名称。在大多数情况下,您可以去掉并忽略sectionDate,只显示类别名称和相应的总数(见下文)。但是对于第一个部分,实际上是任何给定的sectionDate的第一个部分,添加一个额外的视图(到section header视图),显示sectionDate和该sectionDate的总计
  • 确定给定的部分是否是sectionDate的第一部分有点棘手。您可以检索上一节的名称并比较节日期
  • 要折叠/展开节,请维护一个数组,其中包含每个节的折叠/展开状态。如果节已折叠,请在tableView
    numberOfRowsInSection
    datasource方法中返回0;如果扩展,请使用FRC提供的数字
  • 对于类别总计,迭代相关部分的
    对象
    数组(或使用合适的
    .reduce
    实现相同的结果)
  • 对于sectionDate总计,过滤FRC的
    获取对象
    ,以仅包括相关
    sectionDate
    费用
    对象,然后迭代或。减少过滤的数组

  • 如果有任何需要澄清的地方,我很乐意添加或修改。

    我感谢@pbasdf的回答,但我觉得在长时间不看代码之后,我很难对解决方案了如指掌

    我现在要做的不是获取
    Expense
    对象,而是为子部分本身定义了一个新实体(
    CategoryGroup
    ,我还将创建一个
    TagGroup
    )并获取这些实体。这些实体引用了它们所包含的
    费用
    对象,以及表示该组的
    类别
    标记
    。这是我的(部分完成)数据模型:

    我的
    NSFetchedResultsController
    现在的代码要简单得多:

    let fetchedResultsController: NSFetchedResultsController<CategoryGroup> = {
        let fetchRequest = NSFetchRequest<CategoryGroup>(entityName: "CategoryGroup")
        fetchRequest.sortDescriptors = [
            NSSortDescriptor(key: #keyPath(CategoryGroup.sectionDate), ascending: false)
        ]
        return NSFetchedResultsController(fetchRequest: fetchRequest,
                                          managedObjectContext: Global.coreDataStack.viewContext,
                                          sectionNameKeyPath: #keyPath(CategoryGroup.sectionDate),
                                          cacheName: "CacheName")
    }()
    
    让fetchedResultsController:NSFetchedResultsController={
    let fetchRequest=NSFetchRequest(entityName:“CategoryGroup”)
    fetchRequest.sortDescriptors=[
    NSSortDescriptor(键:#键路径(CategoryGroup.sectionDate),升序:false)
    ]
    返回NSFetchedResultsController(fetchRequest:fetchRequest,
    managedObjectContext:Global.coreDataStack.viewContext,
    sectionNameKeyPath:#keyPath(CategoryGroup.sectionDate),
    cacheName:“cacheName”)
    }()
    

    缺点是,我现在必须编写额外的代码,以确保无论何时创建/更新/删除
    费用
    类别
    ,都能正确定义实体之间的关系,但这对我来说是一个可以接受的折衷,因为在代码中更容易理解。

    在该日期分组的所有项目的
    sectionDate
    是否完全相同?@JonRose-Yes。我有一个
    Expense
    的扩展,它设置
    sectionDate
    无论何时
    datespend