首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >UISearchController NSFetchResultsController

UISearchController NSFetchResultsController
EN

Stack Overflow用户
提问于 2015-04-08 06:32:18
回答 1查看 1.2K关注 0票数 0

我得到了一个错误:

CoreData:错误:严重的应用程序错误。在调用NSFetchedResultsController :时,从-controllerDidChangeContent的委托中捕获了一个异常。尝试从第0节中删除第5行,该部分在使用userInfo (null)更新之前只包含1行,如果我编辑第一或第二行,而不是最后一次,则所有操作都正常。

我有一个tableview和UISearchController,当我从tableview触摸到行时,它会将我发送到另一个vc中,在那里我可以编辑我的日记。一切都很好,除非我搜索了一些东西,如果结果是我的TableView的最后一个条目,当我试图编辑和保存它时,它会给我我上面写的错误。

代码语言:javascript
复制
@implementation PlumbListTableViewController


-(void)viewDidLoad {
    [super viewDidLoad];
  [self.fetchedResultsController performFetch:nil];
 }

-(void) viewWillAppear:(BOOL)animated {
    [super viewWillAppear:YES];

   self.searchController =[[UISearchController alloc] initWithSearchResultsController:nil];

    self.searchController.searchResultsUpdater = self;
    self.searchController.dimsBackgroundDuringPresentation = NO;
    self.searchController.searchBar.frame = CGRectMake(self.searchController.searchBar.frame.origin.x, self.searchController.searchBar.frame.origin.y, self.searchController.searchBar.frame.size.width, 44.0);

    self.tableView.tableHeaderView = self.searchController.searchBar;
   self.searchController.searchBar.delegate = self;

     self.tabBarController.tabBar.hidden = NO;
    [self showTotalSum];
    [self.tableView reloadData];

}

-(void)searchBarCancelButtonClicked:(UISearchBar *)searchBar{
[self.tableView reloadData];
}

- (void)searchForText:(NSString *)searchText
{
    CoreDataStack *coreDataStack = [CoreDataStack defaultStack];
    NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"AddEntry"];
    fetchRequest.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"date" ascending:NO]];
    if (self.searchController.searchBar.text.length == 0) {
         NSError *error = nil;
        self.filteredList = [coreDataStack.managedObjectContext executeFetchRequest:fetchRequest error:&error];
    } else {

    if (coreDataStack.managedObjectContext) {

   NSPredicate *predicate = [NSPredicate predicateWithFormat:@"titluPlumb contains[c] %@", searchText];
        [fetchRequest setPredicate:predicate];
          NSError *error = nil;
        self.filteredList = [coreDataStack.managedObjectContext executeFetchRequest:fetchRequest error:&error];
    }
    }
}



- (void)updateSearchResultsForSearchController:(UISearchController *)searchController
{
    NSString *searchString = searchController.searchBar.text;

    [self searchForText:searchString ];
    [self.tableView reloadData];

}

-(void)searchBar:(UISearchBar *)searchBar selectedScopeButtonIndexDidChange:(NSInteger)selectedScope
{
    [self updateSearchResultsForSearchController:self.searchController];
}

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {


    if ([segue.identifier isEqualToString:@"edit"]) {
        UITableViewCell *cell = sender;
        NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
        UINavigationController *navigationController = segue.destinationViewController;
        PlumbAddViewController *entryViewController = (PlumbAddViewController *)navigationController.topViewController;

        if (self.searchController.active) {
            entryViewController.entry = [self.filteredList objectAtIndex:indexPath.row];
        } else {
        entryViewController.entry = [self.fetchedResultsController objectAtIndexPath:indexPath];
        }
   }
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    // Return the number of sections.

    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    // Return the number of rows in the section.

    if (self.searchController.active)
    {
           return [self.filteredList count];
      }
    else
    {
        id <NSFetchedResultsSectionInfo> sectionInfo = [self.fetchedResultsController sections][section];
        return [sectionInfo numberOfObjects];
   }

}


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

    static NSString *CellIdentifier = @"Cell";
    ConfigureCellPlumb *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
    AddEntry *entry = nil;

    if (self.searchController.active){

        entry = [self.filteredList objectAtIndex:indexPath.row];

    } else {

           entry = [self.fetchedResultsController objectAtIndexPath:indexPath];
    }

    cell.titluView.text = entry.titluPlumb;
    cell.descriereView.text = entry.bodyPlumb;

    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateFormat:@"MM/dd/yyyy"];
    NSDate *date = [NSDate dateWithTimeIntervalSince1970:entry.date];
    cell.dataLabel.text = [dateFormatter stringFromDate:date];

    if (entry.imageDataPlumb) {
        cell.imagineView.image = [UIImage imageWithData:entry.imageDataPlumb];
    } else {
        cell.imagineView.image = [UIImage imageNamed:@"icn_noimage"];
    }

    return cell;

}


- (NSFetchRequest *)entryListFetchRequest {
    NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"AddEntry"];

    fetchRequest.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"date" ascending:NO]];

    return fetchRequest;
}

- (NSFetchedResultsController *)fetchedResultsController {
    if (_fetchedResultsController != nil) {
        return _fetchedResultsController;
    }

    CoreDataStack *coreDataStack = [CoreDataStack defaultStack];
    NSFetchRequest *fetchRequest = [self entryListFetchRequest];

    _fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:coreDataStack.managedObjectContext sectionNameKeyPath:@"sectionName" cacheName:nil];
    _fetchedResultsController.delegate = self;

    return _fetchedResultsController;
}

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    AddEntry *entry = [self.fetchedResultsController objectAtIndexPath:indexPath];

    CoreDataStack *coreDataStack = [CoreDataStack defaultStack];
    [[coreDataStack managedObjectContext] deleteObject:entry];
    [coreDataStack saveContext];
}



- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {

    [self.tableView beginUpdates];
}

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {

    switch (type) {
        case NSFetchedResultsChangeInsert:
            [self.tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
            break;
        case NSFetchedResultsChangeDelete:
            [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
            break;
        case NSFetchedResultsChangeUpdate:
            [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
            break;
        case NSFetchedResultsChangeMove:
            [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
            [self.tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
            break;
    }
}

- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id<NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {

    switch (type) {
        case NSFetchedResultsChangeInsert:
            [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationAutomatic];
            break;
        case NSFetchedResultsChangeDelete:
            [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationAutomatic];
            break;
        case NSFetchedResultsChangeUpdate:
            [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationAutomatic];
            break;
        }

}

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {

    [self.tableView endUpdates];

}

@end

更新:

代码语言:javascript
复制
- (NSFetchRequest *)entryListFetchRequest {
    self.searchFetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"AddEntry"];

    self.searchFetchRequest.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"date" ascending:NO]];





    return self.searchFetchRequest;
}


- (NSFetchedResultsController *)fetchedResultsController {
    if (_fetchedResultsController != nil) {
        return _fetchedResultsController;
    }
    self.coreDataStack = [CoreDataStack defaultStack];
    NSFetchRequest *fetchRequest = [self entryListFetchRequest];
    _fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.coreDataStack.managedObjectContext sectionNameKeyPath:@"sectionName" cacheName:nil];
    _fetchedResultsController.delegate = self;

    if (self.searchController.searchBar.text.length != 0) {
        NSString *searchText = self.searchController.searchBar.text;
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"titluPlumb contains[c] %@", searchText];
        [self.searchFetchRequest setPredicate:predicate];

             NSError *error = nil;
        self.filteredList = [self.coreDataStack.managedObjectContext executeFetchRequest:self.searchFetchRequest error:&error];
    }


return _fetchedResultsController;
}

更新2

代码语言:javascript
复制
- (NSFetchedResultsController *)fetchedResultsController {
    if (_fetchedResultsController != nil) {
        return _fetchedResultsController;
    }
    self.coreDataStack = [CoreDataStack defaultStack];
    NSFetchRequest *fetchRequest = [self entryListFetchRequest];

    if (self.searchController.searchBar.text.length !=0) {
       NSString *searchText = self.searchController.searchBar.text;
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"titluPlumb contains[c] %@", searchText];
        fetchRequest.predicate = predicate;
    }

    _fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.coreDataStack.managedObjectContext sectionNameKeyPath:@"sectionName" cacheName:nil];
    _fetchedResultsController.delegate = self;

    return _fetchedResultsController;
}


- (void)updateSearchResultsForSearchController:(UISearchController *)searchController
{

self.fetchedResultsController =0;self.tableView reloadData;

代码语言:javascript
复制
    }
}

更新3

代码语言:javascript
复制
#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    // Return the number of sections.

    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    // Return the number of rows in the section.

        id <NSFetchedResultsSectionInfo> sectionInfo = [self.fetchedResultsController sections][section];
        return [sectionInfo numberOfObjects];


}


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

    static NSString *CellIdentifier = @"Cell";
    ConfigureCellPlumb *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
    AddEntry *entry = nil;

           entry = [self.fetchedResultsController objectAtIndexPath:indexPath];


    cell.titluView.text = entry.titluPlumb;
    cell.descriereView.text = entry.bodyPlumb;

    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateFormat:@"MM/dd/yyyy"];
    NSDate *date = [NSDate dateWithTimeIntervalSince1970:entry.date];
    cell.dataLabel.text = [dateFormatter stringFromDate:date];

    if (entry.imageDataPlumb) {
        cell.imagineView.image = [UIImage imageWithData:entry.imageDataPlumb];
    } else {
        cell.imagineView.image = [UIImage imageNamed:@"icn_noimage"];
    }

    return cell;

}

更新4

代码语言:javascript
复制
- (NSFetchedResultsController *)fetchedResultsController {
    if (_fetchedResultsController != nil) {
        return _fetchedResultsController;
    }
    self.coreDataStack = [CoreDataStack defaultStack];
   self.searchFetchRequest = [self entryListFetchRequest];

    if (self.searchController.searchBar.text.length !=0) {
       NSString *searchText = self.searchController.searchBar.text;
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"titluPlumb contains[c] %@", searchText];
        self.searchFetchRequest.predicate = predicate;
        [self.tableView reloadData];

    }

    _fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:self.searchFetchRequest managedObjectContext:self.coreDataStack.managedObjectContext sectionNameKeyPath:@"sectionName" cacheName:nil];
    _fetchedResultsController.delegate = self;


    return [_fetchedResultsController fetchedObjects];
}


- (void)updateSearchResultsForSearchController:(UISearchController *)searchController
{
 self.fetchedResultsController = nil;
    [self.tableView reloadData];


     NSLog(@"%@", self.searchFetchRequest.predicate);
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-04-08 06:39:15

问题是表视图同时由两个源驱动(在这个场景中),因为搜索时没有完全关闭FRC。所以,您进行搜索并进行编辑,FRC会看到这一点并尝试更新表,但是--该表目前没有显示FRC行--所以有时会失败。

或者使用FRC通过更改fetch请求上的谓词来执行搜索,或者在搜索完成时销毁FRC并重新创建它。

因此,将FRC方法更改为:

代码语言:javascript
复制
- (NSFetchedResultsController *)fetchedResultsController {
    if (_fetchedResultsController != nil) {
        return _fetchedResultsController;
    }
    self.coreDataStack = [CoreDataStack defaultStack];
    NSFetchRequest *fetchRequest = [self entryListFetchRequest];

    if (self.searchController.searchBar.text.length != 0) {
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"titluPlumb contains[c] %@", searchText];
        fetchRequest.predicate = predicate;
    }

    _fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.coreDataStack.managedObjectContext sectionNameKeyPath:@"sectionName" cacheName:nil];
    _fetchedResultsController.delegate = self;

    return _fetchedResultsController;
}

每当您开始搜索/更改搜索文本/结束搜索时,请执行:

代码语言:javascript
复制
self.fetchedResultsController = nil;
[self.tableView reloadData];
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29507506

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档