核心数据和表视图 [英] Core Data and Table Views

查看:76
本文介绍了核心数据和表视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

情况:



我有一笔追踪iOS应用程式的费用,我将费用明细视图控制器的费用存入表格视图,显示费用清单类别和金额。



在tableview的顶部,是一个带有CALENDAR按钮的UIView,一个显示日期的UILabel文本(例如:2012年10月23日))和另外2个按钮。
按下日历按钮可打开一个包含当前日期的自定义日历,两个按钮用于相应地递减和递增日期。



我想根据核心数据实体费用中属性的日期保存费用。



问题:假设我按日历按钮并从那里选择一些随机日期,其下方的表视图应显示该日的特定费用。我的意思是我想要表视图只显示特定的日期的费用,如果我按按钮增加日期或减少日期,表视图应该显示一天的费用。我使用NSFetchedResultsController和Core Data为了节省我的费用。



有关如何实现这一点的任何想法?这里是FRC的代码。

   - (NSFetchedResultsController *)fetchedResultsController 

{

if(_fetchedResultsController!= nil)
{
return _fetchedResultsController;
}

AppDelegate * applicationDelegate =(AppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext * context = [applicationDelegate managedObjectContext];

NSFetchRequest * request = [[NSFetchRequest alloc] init];

[请求setEntity:[NSEntityDescription entityForName:@MoneyinManagedObjectContext:context]];

NSSortDescriptor * sortDescriptor1 =
[[NSSortDescriptor alloc] initWithKey:@rowNumber
ascending:YES];

NSArray * descriptors = [NSArray arrayWithObjects:sortDescriptor1,nil];

[request setSortDescriptors:descriptors];
[request setResultType:NSManagedObjectResultType];
[request setIncludesSubentities:YES];

[sortDescriptor1 release];

self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request
managedObjectContext:context
sectionNameKeyPath:nil
cacheName:nil];
self.fetchedResultsController.delegate = self;

[request release];

NSError * anyError = nil;

if(![_ fetchedResultsController performFetch:& anyError])
{
NSLog(@错误提取:%@,anyError);
}

return _fetchedResultsController;非常感谢你们。


你必须创建一个新的 NSFetchedResultsController 和一个新的 NSFetchRequest 具有适当设置的 NSPredicate

  NSPredicate * predicate = [NSPredicate predicateWithFormat:@(date ==%@),dateToFilterFor]; 
NSFetchRequest * fetchRequest = [[NSFetchRequest alloc] init];
//根据需要编辑实体名称。
NSEntityDescription * entity = [NSEntityDescription entityForName:@ExpenseinManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
[fetchRequest setPredicate:predicate];

// ...

NSFetchedResultsController * aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:@SomeCacheName];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;

不要忘记调用 [self.tableView reloadData]; <



编辑:
您可以将一个谓词分配给 NSFetchRequest ,然后将其分配给fetchedResultsController。

  NSPredicate * predicate = [NSPredicate predicateWithFormat:@(date ==%@ ),dateToFilterFor]; 

如果您通过调用 [fetchRequest setPredicate:predicate ]; 您告诉提取的请求只提取结果 NSManagedObject 的日期属性与您在谓词中提供的日期匹配。



因此,如果您在用户选择日期后调用了一个方法,您可以这样修改:

   - (void)userDidSelectDate:(NSDate *)date 
{
NSFetchRequest * fetchRequest = [[NSFetchRequest alloc] init];
//根据需要编辑实体名称。
NSEntityDescription * entity = [NSEntityDescription entityForName:@EventinManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];


//这里创建过滤结果的谓词,只显示具有所选日期的谓词
NSPredicate * predicate = [NSPredicate predicateWithFormat:@(date == %@),date];
[fetchRequest setPredicate:predicate];

//将批量大小设置为合适的数量。
[fetchRequest setFetchBatchSize:20];

//根据需要编辑排序键。
NSSortDescriptor * sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@timeStampascending:NO];
NSArray * sortDescriptors = @ [sortDescriptor];

[fetchRequest setSortDescriptors:sortDescriptors];

//如果适当,编辑段名称键路径和缓存名称。
//节的名称键路径的nil表示没有节。
NSFetchedResultsController * aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:@Master];
aFetchedResultsController.delegate = self;

//这里你用这个新创建的替换旧的FRC
self.fetchedResultsController = aFetchedResultsController;


NSError * error = nil;
if(![self.fetchedResultsController performFetch:& error]){
//用代码替换这个实现,以适当地处理错误。
// abort()导致应用程序生成崩溃日志并终止。您不应在运送应用程序中使用此功能,但在开发过程中可能很有用。
NSLog(@未解析的错误%@,%@,错误,[错误userInfo]);
abort();
}

//最后你告诉tableView重新加载它的数据,然后它会要求你的新FRC的新数据
[self.tableView reloadData];


}

请注意,如果您不使用ARC(你应该),你必须正确释放分配的对象。


Scenario :

I have an expense tracking iOS Application and I am storing expenses from a expense detail view controller into a table view that shows the list of expenses along with the category and amount.

On the top of the tableview, is a UIView with CALENDAR button, a UILabel text showing the date (for example: Oct 23, 2012 (Sun)) and 2 more buttons on the side. The pressing of the calendar button opens up a custom calendar with the current date and the two buttons are for decrementing and incrementing the date correspondingly.

I want to save the expenses according to the date which is an attribute in my Core data entity "Expense".

Question: Suppose I press the calendar button and choose some random date from there, the table view underneath it, should show that day's particular expenses. What I mean is I want the table view to just show a particular date's expenses and if I press the button for incrementing the date or decrementing the date, the table view should show that day's expenses. I am using NSFetchedResultsController and Core Data in order to save my expenses.

Any thoughts on how I would achieve this? Here's the code for FRC.

-(NSFetchedResultsController *)fetchedResultsController

{

if(_fetchedResultsController != nil)
{
return _fetchedResultsController;
}

AppDelegate * applicationDelegate = (AppDelegate *) [[UIApplication sharedApplication] delegate];
NSManagedObjectContext * context = [applicationDelegate managedObjectContext];

NSFetchRequest * request = [[NSFetchRequest alloc]init];

[request setEntity:[NSEntityDescription entityForName:@"Money" inManagedObjectContext:context]];

NSSortDescriptor *sortDescriptor1 =
[[NSSortDescriptor alloc] initWithKey:@"rowNumber"
                        ascending:YES];

NSArray * descriptors = [NSArray arrayWithObjects:sortDescriptor1, nil];

[request setSortDescriptors: descriptors];
[request setResultType: NSManagedObjectResultType];
[request setIncludesSubentities:YES];

[sortDescriptor1 release];

self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request
                                                                  managedObjectContext:context
                                                                  sectionNameKeyPath:nil
                                                                           cacheName:nil];
self.fetchedResultsController.delegate = self;

[request release];

NSError *anyError = nil;

if(![_fetchedResultsController performFetch:&anyError])
{
NSLog(@"error fetching:%@", anyError);
} 

return _fetchedResultsController;
}

Thanks guys.

解决方案

You would have to create a new NSFetchedResultsController with a new NSFetchRequest that has an appropriately set NSPredicate:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(date == %@)", dateToFilterFor];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Expense" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
[fetchRequest setPredicate:predicate];

// ...

NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:@"SomeCacheName"];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;

Don't forget to call [self.tableView reloadData]; after assigning the new FRC.

Edit: You can assign a predicate to an NSFetchRequest which then is assigned to the fetchedResultsController. You can think of the predicate as a filter.

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(date == %@)", dateToFilterFor];

If you add this to the fetch request by calling [fetchRequest setPredicate:predicate]; you tell the fetched request to only fetch results where to date property of the NSManagedObject matches the date you provide in the predicate. Which is exactly what you want here.

So if you have a method that's called after the user selected a date you could modify it like this:

- (void)userDidSelectDate:(NSDate *)date
{
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    // Edit the entity name as appropriate.
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Event" inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entity];


    //Here you create the predicate that filters the results to only show the ones with the selected date
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(date == %@)", date];
    [fetchRequest setPredicate:predicate];

    // Set the batch size to a suitable number.
    [fetchRequest setFetchBatchSize:20];

    // Edit the sort key as appropriate.
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"timeStamp" ascending:NO];
    NSArray *sortDescriptors = @[sortDescriptor];

    [fetchRequest setSortDescriptors:sortDescriptors];

    // Edit the section name key path and cache name if appropriate.
    // nil for section name key path means "no sections".
    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:@"Master"];
   aFetchedResultsController.delegate = self;

   //Here you replace the old FRC by this newly created
   self.fetchedResultsController = aFetchedResultsController;


   NSError *error = nil;
   if (![self.fetchedResultsController performFetch:&error]) {
     // Replace this implementation with code to handle the error appropriately.
     // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    abort();
   }

   //Finally you tell the tableView to reload it's data, it will then ask your NEW FRC for the new data
   [self.tableView reloadData];


}

Notice that if you're not using ARC (which you should) you'd have to release the allocated objects appropriately.

这篇关于核心数据和表视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆