核心数据:如何显示 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
来“实时”跟踪结果集中的更改,如果您需要在数据库更改时准确计算,则需要刷新结果。
* 要按日期和年份分组,您需要将日期字段中的日期和年份提取到单独的字段中(例如 day
和 year
),然后在获取请求中按这些字段分组:
[r setPropertiesToGroupBy:@[@"year"]];//to group by year alone
并将year
添加到要获取的属性中。
编辑:如果您对特定年份(或一年中的某一天)感兴趣,则必须将年份和日期与日期分开(正如我之前提到的)。 然后只需设置一个谓词以按您需要的年份进行过滤:
[r setPredicate:[NSPredicate predicateWithFormat:@"year = %d",someYear]];
【讨论】:
我明白了,但是如果用户想在选择特定年份时看到这些值怎么办(我还得弄清楚他应该怎么做)。 这是我答案中结果的子集 ==> 添加谓词来过滤您需要的内容(请参阅我的编辑) 太好了,这很有帮助,尽管我仍然面临谓词的一些问题,因为应该从用户输入中获取“someYear”,但我不确定是从什么(文本字段、UIPicker 等)。在任何情况下,有没有办法获取先前的值和用户即将输入的值旁边的值(这将由相关实体中的日期属性标识)【参考方案2】:有两种主要的方法:
我。使用NSFetchedResultsController
在cellForRowAtIndexPath
中手动执行此操作
- (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