刷新NSFetchedResultsController数据? [英] Refresh NSFetchedResultsController data?

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

问题描述

我可以在我的应用程序中创建新的托管对象,在一个单独的视图中,我有一个表视图,其中显示了我有的所有对象。



当我创建一个新的托管对象(在一个完全独立的视图),我发送一个通知,试图让我的表视图重新加载与新数据,包括我刚刚创建的新对象。



我没有编辑表视图。



只有一个管理上下文。



我无法掌握我做错了什么。如果我关闭应用程序,并重新启动我的新对象是在表视图中。我试图调用reloadData当我收到通知一个新的对象,我已经尝试再次执行抓取,但我所有的最后是一个空表视图。



在代码方面,我的ListViewController:

  @interface MyNotesViewController:UIViewController 
{
NSManagedObjectContext * __managedObjectContext;
UITableView * _notesTableView;
MyNotesTableViewDelegate_DataSource * _tableDelegate_DataSource;
}

我的viewDidLoad看起来像这样:

   - (void)viewDidLoad 
{
[super viewDidLoad];

_tableDelegate_DataSource = [[MyNotesTableViewDelegate_DataSource alloc] init];
_tableDelegate_DataSource.managedObjectContext = __managedObjectContext;
[_notesTableView setDataSource:_tableDelegate_DataSource];

NSError * _coreDataError;
BOOL success = [[_tableDelegate_DataSource fetchedResultsController] performFetch:& _coreDataError];

if(success){
[_notesTableView reloadData];
}
}



在我的委托/数据源对象中, p>

  @interface MyCommutesTableViewDelegate_DataSource:NSObject 

< UITableViewDataSource,NSFetchedResultsControllerDelegate>
{
NSManagedObjectContext * __managedObjectContext;
NSFetchedResultsController * __fetchedResultsController;
}

@property(nonatomic,retain)NSManagedObjectContext * managedObjectContext;

@end

实施摘录:



<$ c $ p> - (NSFetchedResultsController *)fetchedResultsController {
if(!__ fetchedResultsController){
NSFetchRequest * request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription entityForName:@NoteinManagedObjectContext:__ managedObjectContext]];

[request setFetchBatchSize:10];

NSSortDescriptor * sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@noteDateascending:NO];
[request setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];
[sortDescriptor release];

__fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:__ managedObjectContext sectionNameKeyPath:nil cacheName:nil];


__fetchedResultsController.delegate = self;
[request release];

}
return __fetchedResultsController;
}



我在这里有UITableView数据源方法:

   - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
id< NSFetchedResultsSectionInfo> sectionInfo =
[[__fetchedResultsController sections] objectAtIndex:section];
return [sectionInfo numberOfObjects];
}

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

static NSString * CellIdentifier = @NotesTableViewCell ;

NotesTableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil){
NSArray * topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@NotesTableViewCellowner:nil options:nil];
for(id currentObject in topLevelObjects){
if([currentObject isKindOfClass:[UITableViewCell class]]){
cell =(NotesTableViewCell *)currentObject;
break
}
}

}

//配置单元格。
注意* _note = [__fetchedResultsController objectAtIndexPath:indexPath];

[...]

return cell;
}

UPDATE



我还原为简单请求所有对象,因为我必须快速修复我的问题,然后我意识到,在我保存上下文之后,我以前在应用程序启动时使用的获取请求,现在不返回数据,没有错误,但它只是不返回任何东西。



所以我想没有问题,我如何实现NSFetchResultsController。但是,如何在保存一个新对象后,请求开始不返回结果?



注意如果我重新启动,我仍然会得到我的所有对象,包括新添加的对象。



标准请求:

   - (NSArray *)getNotes {
NSFetchRequest * request = [[NSFetchRequest alloc] init];

NSEntityDescription * entity = [NSEntityDescription entityForName:@NoteinManagedObjectContext:[self managedObjectContext]];
[request setEntity:entity];

NSSortDescriptor * sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@noteDateascending:NO];
[request setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];
[sortDescriptor release];

NSError * coreDataError;
NSArray * fetchedObjects = [[self managedObjectContext] executeFetchRequest:request error:& coreDataError];
[request release];

if(fetchedObjects!= nil){
return fetchedObjects;
} else {
NSLog(@ERR:%@,coreDataError);
return nil;
}
}



我等待通知告诉我一个新对象已经添加到Core Data,然后我调用上面的方法,然后调用reloadData在我的tableview ...

解决方案

您正在将 UITableViewController 设置为 NSFetchedResultsControllerDelegate 。那很好。现在尝试在TableViewController中实现 controllerDidChangeContent:方法,如下所示:

   - (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
[self.tableView reloadData];
}

您的 NSFetchedResultsController 监听Core Data中删除的或新的对象,并通知它的委托(你的TableViewController)的变化。检查Xcode中的核心数据模板项目以在 UITableView 中添加和移除动画更好地实现这一点。


I can create new managed objects inside my app, in a separate view I have a table view which shows all the objects I have.

When I create a new managed object (in a totally separate view), I am sending out a notification which is trying to get my table view to reload with the new data which includes the new object i just made.

I'm not editing the table view.

There is only one managed context.

I can't grasp what I am doing wrong. If I close the app and relaunch my new object is in the table view. I am trying to call reloadData when I get the notification a new object has been made, and I've also tried performing the fetch again, but all I end up with is an empty table view.

In terms of code, my ListViewController:

@interface MyNotesViewController : UIViewController
{
    NSManagedObjectContext * __managedObjectContext;
    UITableView * _notesTableView;
    MyNotesTableViewDelegate_DataSource * _tableDelegate_DataSource;
}

My viewDidLoad looks like this:

- (void)viewDidLoad
{
    [super viewDidLoad];

    _tableDelegate_DataSource = [[MyNotesTableViewDelegate_DataSource alloc] init];
    _tableDelegate_DataSource.managedObjectContext = __managedObjectContext;
    [_notesTableView setDataSource:_tableDelegate_DataSource];

    NSError * _coreDataError;
    BOOL success = [[_tableDelegate_DataSource fetchedResultsController] performFetch:&_coreDataError];

    if(success){
        [_notesTableView reloadData];
    }
}

In my delegate/datasource object I have:

@interface MyCommutesTableViewDelegate_DataSource : NSObject 

<UITableViewDataSource, NSFetchedResultsControllerDelegate>
{
    NSManagedObjectContext * __managedObjectContext;
    NSFetchedResultsController * __fetchedResultsController;
}

@property (nonatomic, retain) NSManagedObjectContext *managedObjectContext;

@end

Implementation excerpt:

-(NSFetchedResultsController*)fetchedResultsController{
    if(!__fetchedResultsController){
        NSFetchRequest * request = [[NSFetchRequest alloc] init];
        [request setEntity:[NSEntityDescription entityForName:@"Note" inManagedObjectContext:__managedObjectContext]];

        [request setFetchBatchSize:10];

        NSSortDescriptor * sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"noteDate" ascending:NO];
        [request setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];
        [sortDescriptor release];

        __fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:__managedObjectContext sectionNameKeyPath:nil cacheName:nil];


        __fetchedResultsController.delegate = self;
        [request release];

    }
    return __fetchedResultsController;
}

I have the stander UITableView data source methods here:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    id <NSFetchedResultsSectionInfo> sectionInfo = 
    [[__fetchedResultsController sections] objectAtIndex:section];
    return [sectionInfo numberOfObjects];
}

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

    static NSString *CellIdentifier = @"NotesTableViewCell";

    NotesTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {        
        NSArray * topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"NotesTableViewCell" owner:nil options:nil];
        for(id currentObject in topLevelObjects){
            if([currentObject isKindOfClass:[UITableViewCell class]]){
                cell = (NotesTableViewCell*) currentObject;
                break;
            }
        }

    }

// Configure the cell.
    Note * _note = [__fetchedResultsController objectAtIndexPath:indexPath];

    [...]

    return cell;
}

UPDATE

I reverted to simply requesting all objects because I had to quick fix my problem, and then I realised, after I save my context, my fetch request I had previously used on the app launch, now returns no data, there's no error but it just returns nothing.

So I guess there's no issue with how I'm implementing NSFetchResultsController. But how could the request start not returning results after I save a new object ?

Note I still get all of my objects if I relaunch, including the newly added one.

standard request:

-(NSArray*)getNotes{
    NSFetchRequest * request = [[NSFetchRequest alloc] init];

    NSEntityDescription * entity = [NSEntityDescription entityForName:@"Note" inManagedObjectContext:[self managedObjectContext]];
    [request setEntity:entity];

    NSSortDescriptor * sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"noteDate" ascending:NO];
    [request setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];
    [sortDescriptor release];

    NSError * coreDataError;
    NSArray * fetchedObjects = [[self managedObjectContext] executeFetchRequest:request error:&coreDataError];
    [request release];

    if(fetchedObjects != nil){
        return fetchedObjects;
    } else {
        NSLog(@"ERR: %@", coreDataError);
        return nil;
    }
}

I am waiting for a notification telling me a new object has been added to Core Data, and then I am calling the above method and then calling reloadData on my tableview...

解决方案

You are setting your UITableViewController as the NSFetchedResultsControllerDelegate. That's good. Now try to implement the controllerDidChangeContent: method in the TableViewController like so:

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
   [self.tableView reloadData];
}

Your NSFetchedResultsController will listen to removed or new objects in Core Data and notify its delegate (your TableViewController) of changes. Check the Core Data template project in Xcode to implement this even better with add and removal animations in the UITableView.

这篇关于刷新NSFetchedResultsController数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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