I have a Master-Detail Application created, I implemented a UISearchController for the tableview.
The TableView and detailViews works correctly when the search is blank, but when searching the tableview shows the correctly filtered objects but fail to pass it to the detailView.
Any help would be greatly appreciated. thanks in advance.
#pragma mark -
#pragma mark Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [[self.fetchedResultsController sections] count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
return [sectionInfo numberOfObjects];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
// Display the First Letter of the person's last name as section headings.
//return [[[fetchedResultsController sections] objectAtIndex:section] name];
id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
return [NSString stringWithFormat:@"%@", [sectionInfo name]];
}
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
if (index == 0) {
// search item
[tableView scrollRectToVisible:[[tableView tableHeaderView] bounds] animated:NO];
return -1;
}
return index-1;
}
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
// Return the array of section index titles
NSArray *searchArray = [NSArray arrayWithObject:UITableViewIndexSearch];
return [searchArray arrayByAddingObjectsFromArray:self.fetchedResultsController.sectionIndexTitles];
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//self.navigationItem.leftBarButtonItem = self.editButtonItem;
//UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(insertNewObject:)];
//self.navigationItem.rightBarButtonItem = addButton;
self.detailViewController = (DetailViewController *)[[self.splitViewController.viewControllers lastObject] topViewController];
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Printers" style:UIBarButtonItemStylePlain target:nil action:nil];
//instantiate a search results controller for presenting the search/filter results (will be presented on top of the parent table view)
UITableViewController *searchResultsController = [[UITableViewController alloc] initWithStyle:UITableViewStylePlain];
searchResultsController.tableView.dataSource = self;
searchResultsController.tableView.delegate = self;
//instantiate a UISearchController - passing in the search results controller table
self.searchController = [[UISearchController alloc] initWithSearchResultsController:searchResultsController];
//this view controller can be covered by theUISearchController's view (i.e. search/filter table)
self.definesPresentationContext = YES;
//define the frame for the UISearchController's search bar and tint
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.searchController.searchBar.tintColor = [UIColor whiteColor];
//add the UISearchController's search bar to the header of this table
self.tableView.tableHeaderView = self.searchController.searchBar;
//this ViewController will be responsible for implementing UISearchResultsDialog protocol method(s) - so handling what happens when user types into the search bar
self.searchController.searchResultsUpdater = self;
//this ViewController will be responsisble for implementing UISearchBarDelegate protocol methods(s)
self.searchController.searchBar.delegate = self;
}
#pragma mark - UISearchResultsUpdating
-(void)updateSearchResultsForSearchController:(UISearchController *)searchController {
//get search text from user input
[NSFetchedResultsController deleteCacheWithName:@"Master"];
// Init a fetch request
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Event" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
// Apply an ascending sort for the color items
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"printer" ascending:YES selector:@selector(caseInsensitiveCompare:)];
NSArray *descriptors = [NSArray arrayWithObject:sortDescriptor];
[fetchRequest setSortDescriptors:descriptors];
// Recover query
query = self.searchController.searchBar.text;
if (query && query.length) fetchRequest.predicate = [NSPredicate predicateWithFormat:@"(printer contains[cd] %@)",query];
// Init the fetched results controller
NSError *error;
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"fLetter" cacheName:@"Master"];
self.fetchedResultsController.delegate = self;
if (![[self fetchedResultsController] performFetch:&error]) NSLog(@"Error: %@", [error localizedDescription]);
//now that the tableSections and tableSectionsAndItems properties are updated, reload the UISearchController's tableview
[((UITableViewController *)self.searchController.searchResultsController).tableView reloadData];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:@"showDetail"])
{
NSLog(@"showDetail segue was called...");
if ([self.searchController.searchBar.text isEqualToString:@""])
{
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
Event *object = [[self fetchedResultsController] objectAtIndexPath:indexPath];
DetailViewController *controller = (DetailViewController *)[[segue destinationViewController] topViewController];
[controller setDetailItem:object];
controller.navigationItem.leftBarButtonItem = self.splitViewController.displayModeButtonItem;
controller.navigationItem.leftItemsSupplementBackButton = YES;
NSLog(@"Search Predicate was blank, and the code came here...");
}
else
{
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
Event *object = [self.fetchedResultsController.fetchedObjects filteredArrayUsingPredicate:self.searchPredicate][indexPath.row];
DetailViewController *controller = (DetailViewController *)[[segue destinationViewController] topViewController];
[controller setDetailItem:object];
controller.navigationItem.leftBarButtonItem = self.splitViewController.displayModeButtonItem;
controller.navigationItem.leftItemsSupplementBackButton = YES;
NSLog(@"Searching: section %ld row %ld", (long)indexPath.section, (long)indexPath.row);
NSLog(@"searchPredicate %@", self.searchPredicate); }
[self.searchController.searchBar setText:@""];
}
}
NSIndexPath *indexPath = [self.fetchedResultsController.fetchedObjects filteredArrayUsingPredicate:self.searchPredicate][indexPath.row];
I am quite sure problem is in this line. Where you are getting the most right indexPath I mentioned in the line above?
When you are searching and selecting from a tableView, tableView always return a selected row so use
NSIndexPath *indexPath = [self.searchDisplayController.searchResultsTableView indexPathForSelectedRow];
Instead of
NSIndexPath *indexPath = [self.fetchedResultsController.fetchedObjects filteredArrayUsingPredicate:self.searchPredicate][indexPath.row];