prepareForSegue after UISearchDisplayController

Go To StackoverFlow.com

2

EDIT:

I just found: How to segue from a UISearchBarDisplayController result to a detailViewController

which I'll take a look at!


I'm combining a 'search bar and search display controller' with core data fetchedResultsController using storyboard. That is, I have to differentiate between:

if (self.tableView == self.searchDisplayController.searchResultsTableView) {
    ...

and the case where I've just listed the results fetched from the data store.

However, I'm having trouble getting the right row (index path) in the following case:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue.identifier isEqualToString:@"StoreDetails"]) {
        UINavigationController *navigationController = segue.destinationViewController;
        StoreDetailsTableViewController *controller = (StoreDetailsTableViewController *)navigationController.topViewController;
        controller.managedObjectContext = self.managedObjectContext;

        Store *storeToDetail = nil;
        NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];  // This gives wrong row when having searched using searchDisplayController
        NSLog(@"Row: %i", indexPath.row);                                                   // row is always 0
        if (self.tableView == self.searchDisplayController.searchResultsTableView) {
            storeToDetail = [self.filteredListContent objectAtIndex:indexPath.row];
        } else {
            storeToDetail = [self.fetchedResultsController objectAtIndexPath:indexPath];
        }

         controller.storeToDetail = storeToDetail;
    }
}

which is called after:

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller       shouldReloadTableForSearchString:(NSString *)searchString
{
    [self filterContentForSearchText:searchString scope:@"All"];
    ...

with:

- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
    [self.filteredListContent removeAllObjects];

    for (Store *store in [self.fetchedResultsController fetchedObjects])
    {
        if ([scope isEqualToString:@"All"] || [store.name isEqualToString:scope])
        {
            NSComparisonResult result = [store.name compare:searchText options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch) range:NSMakeRange(0, [searchText length])];
            if (result == NSOrderedSame)
            {
                [self.filteredListContent addObject:store];
            }
        }
    }
}

which is taken from Apple's TableSearch example.

The original problem is twofold:

1) self.tableView doesn't seem to be equal to self.searchDisplayController.searchResultsTableView is prepareForSegue

2) having searched the indexPath (row) is always 0.

I suppose I could use didSelectRow... instead or in combination, but I believe prepare... should be possible?! Also, when experimenting with didSelectRow... I'm sure how to pass the object from the relevant row to the destination controller. That is, I can get the correct indexPath in didSelectRow... but I only know how to get the segue destination in the preparFor...:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{
    Store *storeToDetail = nil;
    if (tableView == self.searchDisplayController.searchResultsTableView)
    {
        storeToDetail = [self.filteredListContent objectAtIndex:indexPath.row];
    }
    else
    {
        storeToDetail = [self.fetchedResultsController objectAtIndexPath:indexPath];
    }

    // How to get segue destination controller and set object?!
    // Before doing:
    [self performSegueWithIdentifier:@"StoreDetails" sender:self];
}

Any help is much appreciated. Maybe a reference to a tutorial which shows how to combine theses things.

Thank you!

2012-04-05 17:38
by marrop


4

In this case the senderargument of prepareForSegue:sender: is set to the table view cell initiating the segue.

Just add a property to your cells that holds the Store belonging to this cell and you don't have to do any of the index path or table view comparison dance.

You should end up with something as simple as

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    FooCell *cell = (FooCell *)[self.tableView dequeueReusableCellWithIdentifier:CELL_IDENTIFIER];
    Foo *foo = [self fooForIndexPath:indexPath];

    cell.foo = foo;
    // additional initialization

    return cell;
}

and

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([segue.identifier isEqualToString:@"view detail"]) {
        DetailViewController *destViewController = segue.destinationViewController;
        destViewController.foo = [(FooCell *)sender foo];
    }
}
2013-11-06 13:58
by NoName
Oh. my. gosh. You just changed my life.

I just added a dataID parameter to my UITableViewCell subclass (which was already further subclassed for every cell in my project), and now, as you said, I don't need to worry about those annoying index paths or table view comparisons anymore!

I really wish I could up vote this more than once. Thanks again - Jacob Pritchett 2013-11-23 10:13



1

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

{

if(self.filteredListContent)

{//NSLog(@"post filtered data";}

else

{//NSLog(@"post all";}

}

2012-04-26 14:54
by Tory Hong


0

You are using the wrong test.

if (self.tableView == self.searchDisplayController.searchResultsTableView) {
  ...

This will always fail, you are asking if two different tableViews are different. The answer is always no.

However, you can test if the sender is from the searchResultsTableView.

NSIndexPath *searchIndexPathOfSelectedCell = [self.searchDisplayController.searchResultsTableView indexPathForCell:sender];

if (searchIndexPathOfSelectedCell) {
  ...
2014-03-28 19:12
by Steffen Frost
Ads