UIWebView shouldStartLoadWithRequest ne se triggers qu'une seule fois lors de l'appel d'une vue modale depuis l'intérieur

J'ai une partie de mon application écrite en JS et fonctionnant à l'intérieur d'un WebView. J'utilise la méthode UIWebView shouldStartLoadWithRequest pour capturer des requêtes http comme moyen de communication entre JS et obj-c. Cela fonctionne très bien jusqu'à ce que je tente de charger un controller Modal View sur ma webview à partir de la méthode shouldStartLoadWithRequest. Une fois que cela se produit, shouldStartLoadWithRequest n'est plus appelé. Parfois, j'ai besoin de rejeter ce controller de vue modale et revenir à la webview et faire certaines choses et ensuite présenter à nouveau le controller modal. Le controller modal arrive la première fois très bien, puis je le rejette et tente de le présenter à nouveau en naviguant vers une URL à partir de javascript et il ne se présentera plus. Les NSLogs à l'intérieur de shouldStartLoadWithRequest ne sont jamais exécutés.

Dans mon javascript, je fais quelque chose comme ceci:

window.location='myapp:whateverMethod'; 

Le code objective c ressemble à ceci:

 - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { NSSsortingng *requestSsortingng = [[request URL] absoluteSsortingng]; NSLog(@"REQUEST URL: %@", requestSsortingng); if([requestSsortingng hasPrefix:@"myapp:"]) { NSArray *components = [requestSsortingng componentsSeparatedBySsortingng:@":"]; NSSsortingng *function = [components objectAtIndex:1]; if([self respondsToSelector:NSSelectorFromSsortingng(function)]) { [self performSelector:NSSelectorFromSsortingng(function)]; } return NO; } return YES; } -(void) whateverMethod { NSLog(@"whateverMethod called!"); // This is a quick way to grab my view controller from the storyboard, so assume it exists UIViewController *splash = [self.storyboard instantiateViewControllerWithIdentifier:@"splashViewController"]; [self presentModalViewController:splash animated:NO]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC), dispatch_get_current_queue(), ^{ [self dismissModalViewController:splash animated:NO]; }); } 

À ce stade, mon webview est toujours visible. Je navigue de page en page dans ma webapp et tout javascript fonctionne bien, mais la méthode déléguée "shouldStartLoadWithRequest" du webview n'est plus appelée. Je ne peux pas comprendre pourquoi. Quelqu'un a-t-il une idée?

J'ai remarqué que Cordova ne définit pas la propriété window.location. Au lieu de cela, il a deux options: il crée un iframe et définit le src de l'iframe à cette URL, ou il crée un object XMLHttpRequest par exemple dans la fonction iOSExec ():

  if (bridgeMode) { execXhr = execXhr || new XMLHttpRequest(); // Changeing this to a GET will make the XHR reach the URIProtocol on 4.2. // For some reason it still doesn't work though... execXhr.open('HEAD', "file:///!gap_exec", true); execXhr.setRequestHeader('vc', cordova.iOSVCAddr); if (shouldBundleCommandJson()) { execXhr.setRequestHeader('cmds', nativecomm()); } execXhr.send(null); } else { execIframe = execIframe || createExecIframe(); execIframe.src = "gap://ready"; } 

Cela étant dit, il peut être utile d'utiliser quelque chose comme Cordova au lieu d'essayer de le rouler vous-même (même si c'est juste l'intégration de leur controller de vue), car ils gèrent beaucoup de maux de tête avec les delegates webview.

Je viens d'avoir le même problème, mais lié à l'utilisation d'une ancre href = "#".

Cette réponse Stack Overflow l'a sortingée

Il y a plus de réponses sur ce sujet qui traitent de widow.location, donc vous pouvez avoir de la chance avec eux.

Check out Cordova et ils ont leur propre système de queue, pas vraiment une aide. Mais…

La réponse de Disobedient Media m'a donné une idée. Au lieu de window.location, pourquoi ne pas essayer window.location.hash.

Maintenant, un certain code JS pour la journalisation est:

 function sendMsgToNative(msg) { window.location.hash = '~cmd~' + msg; } console.log = function (msg) { sendMsgToNative('log~js ' + msg); }; 

et le code Objective-C est:

 NSSsortingng *req = [request.URL absoluteSsortingng]; NSArray *components = [req componentsSeparatedBySsortingng:@"~"]; // Check for your protocol if ([components count] > 1 && [(NSSsortingng *)[components objectAtIndex:1] isEqualToSsortingng:@"cmd"]) { // Look for specific actions if ([(NSSsortingng *)[components objectAtIndex:2] isEqualToSsortingng:@"log"]) { NSSsortingng *logStr = [(NSSsortingng *)[components objectAtIndex:3] ssortingngByReplacingPercentEscapesUsingEncoding: NSUTF8SsortingngEncoding]; LOGI("%@", logStr); } } 

Vous obtenez l'URL complète, y compris 'http: …' alors j'ai choisi tilde au lieu de deux points, et incrémenté les indices. Maintenant, vous pouvez vous connecter tout bon gré mal gré et envoyer n'importe quel nombre de commands que vous voulez et ils vont tous passer à travers 🙂

J'ai (avec embarras) passé quelques heures à travailler dessus aujourd'hui, et j'ai réalisé que dans mon avisDidDisappear: Je mettais le UIWebViewDelegate à zéro!

Tout ce que je devais faire pour réparer était une fois le modal a été rejeté, re-définir le UIWebViewDelegate et tout a fonctionné à nouveau.