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:

有帮助吗?

解决方案

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]);
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top