I would like to fire an event on touch when a user taps the title of the navigation bar of one of my views.
I\'m at a bit of a loss on whether I can access the view
I didn't want to specify a button as a custom titleView
because that would mean I can't use the standard title anymore. On the other hand, when adding a tap gesture recognizer to the navigation bar, we have to make sure that it doesn't fire when tapping a bar button.
This solution accomplishes both (to be added to a UINavigationBar
subclass):
- (void)awakeFromNib {
// put in -initWithFrame: if initialized manually
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(ft_titleTapped:)];
[self addGestureRecognizer:tap];
}
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
UIView *titleView = [self valueForKey:@"titleView"];
CGRect titleFrame = titleView.frame;
titleFrame.origin.y = 0; // expand to full height of navBar
titleFrame.size.height = self.frame.size.height;
return CGRectContainsPoint(titleFrame, [gestureRecognizer locationInView:self]);
}
- (void)ft_titleTapped:(UITapGestureRecognizer*)sender {
if (sender.state == UIGestureRecognizerStateEnded) {
// could add some checks here that the delegate is indeed a navigation controller
UIViewController *viewController = (id)[((UINavigationController*)self.delegate) topViewController];
if ([viewController respondsToSelector:@selector(titleViewTapped:)]) {
[viewController titleViewTapped:self];
}
}
}
It automatically sends a -titleViewTapped:
message to the view controller (if implemented). In a UITableViewController
subclass you could implement the method like this for a scroll to top feature:
- (void)titleViewTapped:(id)sender {
[self.tableView setContentOffset:CGPointMake(0, -self.tableView.contentInset.top) animated:YES];
}
Caution: we're retrieving the title view using the undocumented -valueForKey:@"titleView"
. It's technically not using a private API but might still fail in a future iOS version!