Reloading UITableView behind UISearchDisplayController

前端 未结 9 2091
南旧
南旧 2021-02-07 11:26

I\'ve run into this really strange phenomenon that I can\'t quite figure out. I have a UITableViewController that manages a UITableView. Pretty simple. I also have a UISearch

相关标签:
9条回答
  • 2021-02-07 11:43

    Fixed it..

    Add the following lines in viewDidLoad

    searchDisplayController.searchResultsTableView.delegate = self;
    searchDisplayController.searchResultsTableView.dataSource = self;
    

    That fixed it for me...

    0 讨论(0)
  • 2021-02-07 11:46

    I ran into this recently as well...the approach I decided on was to queue updates to the main tableView in a suspended serial dispatch queue until the the UISearchDisplayController hides the searchResultsTableView. I would probably consider this a bug as the section headers should not show through the main tableView if the searchResultsTableView has taken over that layer.

    0 讨论(0)
  • 2021-02-07 11:50

    Hopefully you've figured this out by now, but just in case someone stumbles across this question: this is probably happening because your UITableViewController is the data source/delegate for the search table as well as your main table. That is, presumably, you have the same UITableViewDelegate/DataSource methods executing for both table views, and you're returning the same section header for both tables. Make sure you're handling your search results table separately:

    - (NSString *)tableView:(UITableView *)aTableView titleForHeaderInSection:(NSInteger)section {
        if (aTableView == [[self searchDisplayController] searchResultsTableView]) {
            return nil;
        }
        // Return a title appropriate for self.tableView here
    }
    
    0 讨论(0)
  • 2021-02-07 11:51

    Our solution is to do the following. It has only been tested in iOS 7:

    1. In viewForHeaderInSection, return nil if self.searchDisplayController.active is YES
    2. In didHideSearchResultsTableView, call [self.tableView reloadData] to reload the headers when the search table disappears
    0 讨论(0)
  • 2021-02-07 11:51

    My solution was to avoid reloading the table if search results were displaying, then reloading any time the search results were dismissed.

    I had to set a symbolic breakpoint on UITableView reloadData to find all the calls to reload that were causing the section headers to redraw on top of the search table.

    0 讨论(0)
  • 2021-02-07 11:56

    UPDATED AGAIN

    As it turns out, if a table's header is reloaded in the background it pops in front of the search controller no matter what.

    I solved this by disabling the fetchedResultsController (setting it to nil) and letting it load lazily again when needed when the search disappears.

    UPDATED - Original answer below

    In my case I'm using two fetchedResultsControllers one for the main tableview and one for the search.

    I discovered that preventing animations when adding the section headers prevents this bug. So while searchDisplayController.active I simply disable the animation of the section change. see code below.

    - (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
               atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type
    {
        if (!self.reordering) {
            UITableView *myTableView = controller == __fetchedResultsController ? self.tableView : self.searchDisplayController.searchResultsTableView;
            UITableViewRowAnimation animation;
            if (self.searchDisplayController.active) {
                animation = UITableViewRowAnimationNone;
            } else {
                animation = UITableViewRowAnimationFade;
            }
    
            switch(type)
            {
                case NSFetchedResultsChangeInsert:
                    [myTableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:animation];
                    break;
    
                case NSFetchedResultsChangeDelete:
                    [myTableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:animation];
                    break;
            }
        }
    }
    

    ORIGINAL ANSWER

    The other answer doesn't actually work on it's own. The reason is, the header that is showing is not a header in the searchDisplayController's tableview. It's a header from the main tableview that for some reason is being added above the search table view in the view hierarchy.

    I solved this problem by disabling updates to the main tableview while searchDisplayController.active = YES.

    In my case I'm using a lazily loaded fetched results controller so I did it like this:

    - (void)searchDisplayController:(UISearchDisplayController *)controller didHideSearchResultsTableView:(UITableView *)tableView {
        [self.tableView reloadData];
    }
    
    - (void)searchDisplayController:(UISearchDisplayController *)controller willShowSearchResultsTableView:(UITableView *)tableView {
        self.fetchedResultsController.delegate = nil;
        self.fetchedResultsController = nil;
    }
    

    However, I still have the problem that if I want to reloadData on the main tableview so it is seen in the background, the section headers still float in front of the darkened area.

    Does anyone have a better solution for this? It seems like a legitimate bug for viewForHeaderInSection and titleForHeaderInSection when data is reloaded while covered by a UISearchDisplayController.

    The simplest answer for me is to try and override the search view so you can't see the background table. But that takes away from the "Appleness" of the app.

    0 讨论(0)
提交回复
热议问题