核心数据:如何显示 fetchrequest 的结果以计算表格视图单元格中的值

Posted

技术标签:

【中文标题】核心数据:如何显示 fetchrequest 的结果以计算表格视图单元格中的值【英文标题】:Core data: How to display results of a fetchrequest for calculating values in a tableview cell 【发布时间】:2013-07-10 15:29:08 【问题描述】:

我对 ios 比较陌生(如果我不清楚或者问题已在其他地方得到解决,我提前道歉)并且我已经阅读了很多教程来学习基础知识。尽管如此,我在使用核心数据执行以下操作时遇到了问题:

我了解如何使用核心数据从 DB 中获取数据、对其进行排序和显示,但现在我不知道如何以编程方式处理需要的属性(它是我 DB 中表中的临时属性)计算并显示在嵌入导航控制器的 tableview 控制器内的静态 tableview 单元格中。

为了说明:我有一个包含 两个变量( InputValue (integer) 和 inputDate (NSDate) )的表,我想计算每年或每天输入的每个每日值的平均值/最小值/最大值。然后这些值将在 tableview 静态单元格中显示和更新(每个单元格中的计算值。)

编辑:我在此处从 tableview 控制器添加了一些代码:

- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath


    //Configure the cell to show the user value as well as showing the date of input

    PVMesswert *wert = [self.fetchedResultsController objectAtIndexPath:indexPath];
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
   [dateFormatter setDateFormat:@"dd.MM.yyyy"];
           cell.textLabel.text= [[NSString alloc] initWithFormat:@"%@ kWh", wert.inputValue];
    cell.detailTextLabel.text = [dateFormatter stringFromDate:wert.inputDate];

     

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    //should I have a different cell identifier for each row where I want to display a result of the calculations?
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    // Configure the cell.
    [self configureCell:cell atIndexPath:indexPath];
    return cell;


- (NSFetchedResultsController *)fetchedResultsController



     if (_fetchedResultsController != nil) 
            return _fetchedResultsController;
        

        // Create and configure a fetch request with the PVMesswert entity.


        NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
        NSEntityDescription *entity = [NSEntityDescription entityForName:@"PVMessWert" inManagedObjectContext:self.managedObjectContext];
        [fetchRequest setEntity:entity];

        // Create the sort descriptors array.

        NSSortDescriptor *datumsort = [[NSSortDescriptor alloc] initWithKey:@"inputDate" ascending:NO];

        NSSortDescriptor *valueDescriptor = [[NSSortDescriptor alloc] initWithKey:@"InputValue" ascending:YES];

        NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:datumsort, /*authorDescriptor,*/ nil];
        [fetchRequest setSortDescriptors:sortDescriptors];

        // Create and initialize the fetch results controller.


        _fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"dateToString" cacheName:@"Root"];

        _fetchedResultsController.delegate = self;

        // Memory management.

        return _fetchedResultsController;
        

因此,在我拥有的另一个表格视图中,我想显示如下内容:每年的平均/最大/最小输入值(基于属性输入日期 NSDat。)。我应该使用 NSExpression 吗?在这种情况下如何使用?

【问题讨论】:

您需要针对每个对象或整个表格进行这些计算吗?请提供一些上下文(简单的测试用例、实体、您使用的获取请求、代码...)。 你好,我将代码发布为上面的编辑,尽管不是用于计算,这更多的是用于添加和输入的详细视图。我搜索的是另一个 tableview 控制器,其中每个静态单元格显示特定年份数据库中所有当前值的最大值、最小值、平均值(由用户选择) 【参考方案1】:

您应该使用aggregate functions 进行此类计算。

您可以在一个相对较快的获取请求中检索所有最大/最小/平均信息。

聚合函数的代码应如下所示:

//Function expression generator
- (NSExpressionDescription*) aggregateFunction:(NSString*)function
                                    forKeyPath:(NSString*)keyPath
                                          name:(NSString*)name
                                    resultType:(NSAttributeType)resultType

    NSExpression* keyPathExpression = [NSExpression expressionForKeyPath:keyPath];
    NSExpression* funcExpression = [NSExpression expressionForFunction:function arguments:@[keyPathExpression]];
    NSExpressionDescription* expressionDescription  = [NSExpressionDescription new];
    [expressionDescription setName:name];
    [expressionDescription setExpression:funcExpression];
    [expressionDescription setExpressionResultType:resultType];
    return expressionDescription;

您的提取请求应如下所示:

//someValue is an Integer64 property
//someDate is a Date property
NSFetchRequest* r = [NSFetchRequest fetchRequestWithEntityName:@"Product"];
NSExpressionDescription* minValueField = [self aggregateFunction:@"min:"
                                                      forKeyPath:@"someValue"
                                                            name:@"minValue"
                                                      resultType:NSInteger64AttributeType];
NSExpressionDescription* avgValueField = [self aggregateFunction:@"average:"
                                                      forKeyPath:@"someValue"
                                                            name:@"avgValue"
                                                      resultType:NSInteger64AttributeType];
NSExpressionDescription* maxValueField = [self aggregateFunction:@"max:"
                                                      forKeyPath:@"someValue"
                                                            name:@"maxValue"
                                                      resultType:NSInteger64AttributeType];
NSExpressionDescription* minDateField = [self aggregateFunction:@"min:"
                                                     forKeyPath:@"someDate"
                                                           name:@"minVDate"
                                                     resultType:NSDateAttributeType];
NSExpressionDescription* avgDateField = [self aggregateFunction:@"average:"
                                                      forKeyPath:@"someDate"
                                                            name:@"avgDate"
                                                      resultType:NSDateAttributeType];
NSExpressionDescription* maxDateField = [self aggregateFunction:@"max:"
                                                     forKeyPath:@"someDate"
                                                           name:@"maxDate"
                                                     resultType:NSDateAttributeType];

[r setResultType:NSDictionaryResultType];
[r setPropertiesToFetch:@[minValueField,avgValueField,maxValueField,minDateField,avgDateField,maxDateField]];

NSArray* results = [context executeFetchRequest:r error:NULL];

注意事项: * 这将检索单个字典对象中的信息,其键与您为其创建表达式的 name 参数匹配。 * 您不能使用NSFetchedResultsController 来“实时”跟踪结果集中的更改,如果您需要在数据库更改时准确计算,则需要刷新结果。 * 要按日期和年份分组,您需要将日期字段中的日期和年份提取到单独的字段中(例如 dayyear),然后在获取请求中按这些字段分组:

[r setPropertiesToGroupBy:@[@"year"]];//to group by year alone

并将year 添加到要获取的属性中。

编辑:如果您对特定年份(或一年中的某一天)感兴趣,则必须将年份和日期与日期分开(正如我之前提到的)。 然后只需设置一个谓词以按您需要的年份进行过滤:

[r setPredicate:[NSPredicate predicateWithFormat:@"year = %d",someYear]];

【讨论】:

我明白了,但是如果用户想在选择特定年份时看到这些值怎么办(我还得弄清楚他应该怎么做)。 这是我答案中结果的子集 ==> 添加谓词来过滤您需要的内容(请参阅我的编辑) 太好了,这很有帮助,尽管我仍然面临谓词的一些问题,因为应该从用户输入中获取“someYear”,但我不确定是从什么(文本字段、UIPicker 等)。在任何情况下,有没有办法获取先前的值和用户即将输入的值旁边的值(这将由相关实体中的日期属性标识)【参考方案2】:

有两种主要的方法:

我。使用NSFetchedResultsControllercellForRowAtIndexPath 中手动执行此操作

- (UITableViewCell *)tableView:(UITableView *)tableView
    cellForRowAtIndexPath:(NSIndexPath *)indexPath 

    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell =
        [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    // get your managed object
    NSManagedObject *managedObject = [_fetchedResultsController objectAtIndexPath:indexPath];

    // do any computations
    float value1 = [[managedObject valueForKey:@"value1"] floatValue];
    float value2 = [[managedObject valueForKey:@"value2"] floatValue];
    float average = (value1+value2)/2;

    // display average in cell
    cell.textLabel.text = [NSString stringWithFormat:@"Average: %f", average];

    return cell;

二。另一种方法是使用核心数据框架,例如Sensible TableView。除了自动管理在自定义单元格中显示此类计算之外,这些框架还会自动获取您的数据并显示它们。使用 Core Data 为我节省了大量时间。

【讨论】:

感谢这让我对我真正需要的潜在计算有了一个想法。

以上是关于核心数据:如何显示 fetchrequest 的结果以计算表格视图单元格中的值的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI:Core Data @FetchRequest 和 List 显示托管对象 - 在 lockscreemn 上丢失数据

Swift 核心数据 FetchRequest NSData 到 UIIMage

NSArray 作为核心数据 fetchRequest 中的参数

可可 iphone 核心数据谓词一对多 fetchrequest

iOS:在 fetchrequest 中仅获取核心数据中的简单信息

在@FetchRequest 中输入一个动态值,以从 SwiftUI 中的核心数据中获取单个实体