开发者

UISearchBar cancel button crash

I have a UITableView that on didSelectRowAtIndexPath pushes another UITableView to do a search...

    LocationSearchViewController *locationSearchViewController = [[LocationSearchViewController alloc] initWithNibName:@"LocationSearchViewController"  bundle:nil];
    locationSearchViewController.delegate = self;       
    UITableViewCell *cell = [myTableView cellForRowAtIndexPath:indexPath];
    locationSearchViewController.defaultLocation = cell.detailTextLabel.text;

    [[self navigationController]  pushViewController:locationSearchViewController animated:YES];
    [locationSearchViewController release];

The search view contains a UISearchBar with it's cancel button enabled. If the user taps the cancel button the app crashes with an objc_exception_throw. The console displays...

2011-02-06 22:05:43.960 JetLogger[2381:207] * Assertion failure in -[UISearchDisplayController setActive:animated:], /SourceCache/UIKit_Sim/UIKit-1447.6.4/UISearchDisplayController.m:589

If, however, the user taps an item in the table view (search results) I am closing the search view and there is no crash. I can't see why the difference as I am popping the search view with the same code...

In the LocationSearchViewController...

- (void)tabl开发者_开发知识库eView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
   if ([self.delegate respondsToSelector:@selector(locationSearchViewDidDismiss:withLocation:)]) {
    [self.delegate locationSearchViewDidDismiss:self withLocation:[tableView cellForRowAtIndexPath:indexPath].textLabel.text];
   }
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar{
   if ([self.delegate respondsToSelector:@selector(locationSearchViewDidDismiss:withLocation:)]) {
     [self.delegate locationSearchViewDidDismiss:self withLocation:@"No results found"];
   }
}

In the delegate...

- (void)locationSearchViewDidDismiss:(LocationSearchViewController *)controller withLocation:(NSString*)location{   
   if((location != @"") && (location != @"No results found")){
    //update the table data
    [myTableView reloadData];
   }
   [self.navigationController popViewControllerAnimated:YES];
}

Any help is appreciated.

John


Because we pop the viewController, the searchbar loses focus. This causes the setActive to be called but at the time this happens the searchbar is allready deallocated. So we need to set active to no before we pop.

An easy workaround therefore is:

- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
{
    [self.searchDisplayController setActive:NO animated:NO];
    [self.navigationController popViewControllerAnimated:YES]; 
}


I think the provided answers are imperfect, because they indirectly addresses the issue, which is that searchDisplayControllerDidEndSearch: is being called on the deallocated delegate. Calling [self.searchDisplayController setActive:NO animated:NO] may work within searchBarCancelButtonClicked:, but it will fail elsewhere, such as from within searchBarTextDidEndEditing:.

Instead, just clear the delegate directly prior to popping the controller: self.searchDisplayController.delegate = nil;

That will assure that the delegate method will not be called on the deallocated instance.


I've run into the same issue. XCode 4 IOS 4.3

For me the problem was only when focus was inside search bar I've found some workaround that might help.

Here are the code:

static BOOL _cancelBtnClicked = NO;

- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar{
    Log(@"Enter"); 
    if(searchDisplayController.active){
        _cancelBtnClicked = YES;
    }else{
        [self back];
    }
}

- (void)searchDisplayControllerDidEndSearch:(UISearchDisplayController *)controller{
    Log(@"Enter");
    if(_cancelBtnClicked){
        _cancelBtnClicked = NO;
        [self back];
    }
}

-(void)back{
[self.navigationController popViewControllerAnimated:YES];
}


I just ran into this issue.

I get this error when I dismiss the viewcontroller containing the search stuff with popViewControllerAnimated. If you present the same viewcontroller modally, and dismiss using modal dismiss function, this assertion won't fire either.

To fix this issue, I had to add (using your code as an example)

- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar{
   [self.searchController setActive:NO animated:NO];
   if ([self.delegate respondsToSelector:@selector(locationSearchViewDidDismiss:withLocation:)]) {
     [self.delegate locationSearchViewDidDismiss:self withLocation:@"No results found"];
   }
}

This way, searchcontroller is inactive before calling whatever internal functions it wants. It feels like this is a bug with 4.2 sdk though, I need to check this out with new 4.3 gm seed.

Have you found any other solution?

I rather not use the above fix because dismiss animation is little ugly :\


I had the same problem.

- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
{
    [self.searchDisplayController setActive:NO animated:NO];
    [self.navigationController popViewControllerAnimated:YES]; 
}

Did NOT solve it in my case. Instead I called [self.searchDisplayController setActive:NO animated:NO] in a different place, making it being called earlier.

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    // ....

    [self.searchDisplayController setActive:NO animated:NO];
}


Swift Edition

func searchBarCancelButtonClicked(searchBar: UISearchBar) {
    self.searchDisplayController?.active = false
    self.dismissViewControllerAnimated(true, completion: nil)
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜