0

decidePolicyForNavigationAction is not being triggered when the webview loads a new page. It works when everything is initially loaded but then never gets triggered after that.

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction
decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
    NSLog(@"decidePolicyForNavigationActionnavigationAction.request.URL.absoluteString:%@|", navigationAction.request.URL.absoluteString);
    
    
    if (kTestLocalHTML == 1) {
        decisionHandler(WKNavigationActionPolicyAllow);

        return;
    }
    
    
    NSURL *url = navigationAction.request.URL;
    if (url != nil) {
        
        
        //
        // TODO: Trim the url string below as well?
        //       No, because this is being trimmed already in the AppManager methods related to web view URL
        //
        
        NSString *urlString = url.absoluteString;
        WKNavigationType navType = navigationAction.navigationType;
        
        
        //
        // Display the club mobile native login page and log the user out
        // if the webview is about to load the blazor login page URL
        //
        if ([urlString isEqualToString:[AppManager getMobileLoginUrl]]) {
            self.appManager.userLoginDetails = nil;
            [self displayLoginPage];
            
            decisionHandler(WKNavigationActionPolicyCancel);
            return;
        }
        
        
        //
        // Check if link is tapped from webview and if URL string contains the
        // prepended identifier within the JavaScript injection which can be found in
        // "webViewDidFinishLoad" delegate method of webview
        //
        if (navType == WKNavigationTypeLinkActivated && [AppManager isWebViewURL_containsTargetBlank:urlString]) {
            
            //
            // Make sure to ignore the prepended identifier on the URL string
            // before opening it on an external browser
            //
            NSInteger targetBlankIdentifierLength = kIdentifier_TargetBlank.length;
            
            NSURL *url = [NSURL URLWithString:[urlString substringFromIndex:targetBlankIdentifierLength]];
            [[UIApplication sharedApplication] openURL:url];
            
            decisionHandler(WKNavigationActionPolicyCancel);
            return;
        }
        
        
        //
        // Check if url has custom scheme other than "http" & "https" (If is either one of the tags for Telephone "tel", Mail "mailto", SMS "sms", Web Calendar "webcal", etc.)
        //
        // Solution Reference: https://stackoverflow.com/questions/47040471/wkwebview-not-opening-custom-url-scheme-js-opens-custom-scheme-link-in-new-wind
        //      - (Answers of both "hstdt" & "mattblessed")
        //
        // NOTE: It seems loading telephone and mail links do not work when testing on an iOS simulator.
        //
        NSString *urlScheme = url.scheme;
        BOOL isCustomURLscheme = ( ! [urlScheme isEqualToString:@"http"] && ! [urlScheme isEqualToString:@"https"]);
        if (isCustomURLscheme) {
            
            NSURL *url = [NSURL URLWithString:urlString];
            [[UIApplication sharedApplication] openURL:url];
            
            decisionHandler(WKNavigationActionPolicyCancel);
            return;
        }
        
        
        //
        // Get reference to the current URL being requested so that if there
        // will be failure in loading the webview, we have a reference to that URL.
        //
        self.currentUrlRequest = navigationAction.request;
        
        
        // Check if web view URL contains a calendar file to download
        if ([AppManager isWebViewURL_containsCalendarDownload:urlString]) {
            
            //
            // Download and process calendar file either from Events or Dining module
            // and display "New Event" page where user can view its details, edit and save to device calendar
            //
            [self processCalendarFileAndDisplayEventPageWithURLrequest:self.currentUrlRequest];
            
            decisionHandler(WKNavigationActionPolicyCancel);
            return;
        }
        // Check if web view URL contains a PDF file attachment to download
        else if ([AppManager isWebViewURL_containsPDFAttachmentDownload:urlString]) {
            
            // Display document viewer page and pass few parameters for page customization (initial URL to load, navigation bar title)
            UIStoryboard *storyboard = [UIStoryboard storyboardWithName:kStoryboardName bundle:nil];
            UINavigationController *navigationController = [storyboard instantiateViewControllerWithIdentifier:kStoryboardID_OverlayBrowserNavigationController];
            OverlayBrowserViewController *vcOverlay = (OverlayBrowserViewController *)[navigationController topViewController];
            vcOverlay.initialURLtoLoad = urlString;
            vcOverlay.navigationBarTitle = [self getPDFDocumentNameFromURLString:urlString];
            [self presentViewController:navigationController animated:YES completion:nil];
            
            decisionHandler(WKNavigationActionPolicyCancel);
            return;
        }
    }
    
    decisionHandler(WKNavigationActionPolicyAllow);
}

This function is supposed to trigger and detect if the webview is loading the web login page and if that is the case it will logout the user and instead show the apps native login page. However the function is never triggered after the main screen is loaded initially.

Daniel98
  • 3
  • 3
  • Did you set the web view's `navigationDelegate` property? – HangarRash Dec 30 '22 at 01:33
  • I believe i did. @interface HomeViewController () and in viewDidLoad I put self.wkWebMain.navigationDelegate = self; Is this correct or am I missing a step? – Daniel98 Dec 30 '22 at 01:40
  • That's correct. Sorry, I just reread your question and realize that you state that the delegate method is being called initially but then not again. Since it is being called initially we know the delegate is setup correctly. What path does your delegate method take the one time that is does get called? – HangarRash Dec 30 '22 at 01:49
  • After the initial login the delagate is called and the webview loads the url https://encore-uat.jcsmobiletest.com/company-select after a company is selected the homepage is loaded. Once the app is on the homepage the delagate never gets triggered again no matter what other pages the webview navigates to. – Daniel98 Dec 30 '22 at 02:47
  • Are you sure the web page is actually performing a redirect and is not a SPA like Angular which may not be updating the URL? Also how are you setting self.wkWebMain? – RunLoop Dec 30 '22 at 06:53
  • If your delegate object implements the webView:decidePolicyForNavigationAction:preferences:decisionHandler: method, the web view doesn’t call this method. From the doc https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455641-webview?language=objc – Mubin Mall Jan 02 '23 at 07:55

1 Answers1

0

"Are you sure the web page is actually performing a redirect and is not a SPA like Angular which may not be updating the URL? Also how are you setting self.wkWebMain? – RunLoop"

Thanks for this, you were correct and the webpage was acting as an SPA which was the reason the function would call at first on the initial load but not after.

Daniel98
  • 3
  • 3