Question

I wanted to implement a UISearchDisplayController like controller to display search results, and added some log to figure out the logic.

After I saw the logs, I am very curious about how the UISearchDisplayController steals the UISearchBar events.

UISearchDisplayController works without setting the UISearchBarDelegate to itself. And the UISearchBarDelegate is working at the same time outside!

Here are the logs:

searchBarShouldBeginEditing:

searchBarTextDidBeginEditing:

searchDisplayControllerWillBeginSearch:

searchDisplayController:didLoadSearchResultsTableView:

searchBar:shouldChangeTextInRange:replacementText:

searchBar:textDidChange:

searchDisplayController:shouldReloadTableForSearchString:

searchDisplayController:willShowSearchResultsTableView:

searchDisplayController:didShowSearchResultsTableView:

searchBarCancelButtonClicked:

searchBarShouldEndEditing:

searchBarTextDidEndEditing:

searchDisplayController:willHideSearchResultsTableView:

searchDisplayController:didHideSearchResultsTableView:

searchBarShouldBeginEditing:

searchBarTextDidBeginEditing:

searchDisplayControllerWillBeginSearch:

searchBar:shouldChangeTextInRange:replacementText:

searchBar:textDidChange:

searchDisplayController:shouldReloadTableForSearchString:

searchDisplayController:willShowSearchResultsTableView:

searchDisplayController:didShowSearchResultsTableView:

searchBar:shouldChangeTextInRange:replacementText:

searchBarSearchButtonClicked:

searchBarShouldEndEditing:

searchBarTextDidEndEditing:

searchBarCancelButtonClicked:

searchDisplayController:willHideSearchResultsTableView:

searchDisplayController:didHideSearchResultsTableView:

Was it helpful?

Solution

OK, I figured out myself.

You can do that just by adding the UISearchBar delegate property to KVO observation, and then make your implementation as a delegate proxy.

Example Code:


    if (searchBar.delegate) {
        self.searchBarDelegate = searchBar.delegate;
    }

    searchBar.delegate = self;

    [searchBar addObserver:self forKeyPath:@"delegate" options:NSKeyValueObservingOptionNew context:kSearchBarKVOContext];

#pragma mark - KVO
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if (context == kSearchBarKVOContext) {
        [self updateSearchBarDelegate];
    } else {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}

- (void)updateSearchBarDelegate
{
    if (self.searchBar.delegate == self) {
        self.searchBarDelegate = nil;
    } else {
        self.searchBarDelegate = self.searchBar.delegate;
        self.searchBar.delegate = self;
    }
}

#pragma mark - NSObject Overrides
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
    NSMethodSignature *result = [super methodSignatureForSelector:aSelector];

    if (!result) {
        NSObject *obj = (NSObject *)self.searchBarDelegate;

        result = [obj methodSignatureForSelector:aSelector];
    }

    return result;
}

- (void)forwardInvocation:(NSInvocation *)anInvocation
{
    if ([self.searchBarDelegate respondsToSelector:[anInvocation selector]]) {
        [anInvocation invokeWithTarget:self.searchBarDelegate];
    } else {
        [super forwardInvocation:anInvocation];
    }
}

- (BOOL)respondsToSelector:(SEL)aSelector {
    return ([super respondsToSelector:aSelector] ||
            [self.searchBarDelegate respondsToSelector:aSelector]);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top