I am using a UIWebView
and don't want the navigation bar to appear unless the user taps anywhere on the screen that isn't a link.
So I have this code to display the navigation bar after a delay:
- (void)handleTapGesture:(UITapGestureRecognizer *)sender
{
....
[self performSelector:@selector(showNavigationBar) withObject:self afterDelay:0.2];
}
I'm not calling showNavigationBar
immediately when the tap handler is invoked because the user might have tapped on a link in which case the tap hander is called before UIWebView
shouldStartLoadWithRequest
, so if I hid the navigation bar in shouldStartLoadWithRequest
it would flash momentarily onto the screen.
So instead I set it to display after a delay which gives time for the following code to execute within shouldStartLoadWithRequest
(and if the user didn't tap on a link shouldStartLoadWithRequest
isn't called and the navigation bar is displayed, as it should be in that case).
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(showNavigationBar) object:nil];
...
However this isn't working, I've increased the delay time to several seconds and can confirm cancelPreviousPerformRequestWithTarget
is getting called before the navigation bar has been displayed, but when the specified time elapses the bar displays. cancelPreviousPerformRequestWithTarget
is having no effect.
Does anybody know why its not working?
In the documentation of that + (void)cancelPreviousPerformRequestsWithTarget:(id)aTarget selector:(SEL)aSelector object:(id)anArgument
method there is this sentence :
This method removes perform requests only in the current run loop, not all run loops.
If I'm interpreting it correctly it would mean that you need to cancel your action in the same run loop that you launched it. Which is clearly not what you want to do.
A way to go around this would be to have a flag that showNavigationBar
would have to check to see if it should proceed or abort.
Your perform doesn't match your cancel. In the perform you're passing self as the object:
[self performSelector:@selector(showNavigationBar) withObject:self afterDelay:0.2];
In the cancel you're passing nil as the object:
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(showNavigationBar) object:nil];
They don't match, so the delayed perform should not be canceled.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With