J'ai une UIWebView très simple avec le contenu de mon bundle d'application. Je souhaite que tous les liens de la vue Web s'ouvrent dans Safari plutôt que dans la vue Web. Est-ce possible?
J'ai une UIWebView très simple avec le contenu de mon bundle d'application. Je souhaite que tous les liens de la vue Web s'ouvrent dans Safari plutôt que dans la vue Web. Est-ce possible?
Réponses:
Ajoutez ceci au délégué UIWebView:
(modifié pour vérifier le type de navigation. vous pouvez également transmettre des file://
demandes qui seraient des liens relatifs)
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
if (navigationType == UIWebViewNavigationTypeLinkClicked ) {
[[UIApplication sharedApplication] openURL:[request URL]];
return NO;
}
return YES;
}
Version rapide:
func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {
if navigationType == UIWebViewNavigationType.LinkClicked {
UIApplication.sharedApplication().openURL(request.URL!)
return false
}
return true
}
Version Swift 3:
func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool {
if navigationType == UIWebViewNavigationType.linkClicked {
UIApplication.shared.openURL(request.url!)
return false
}
return true
}
Version Swift 4:
func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebView.NavigationType) -> Bool {
guard let url = request.url, navigationType == .linkClicked else { return true }
UIApplication.shared.open(url, options: [:], completionHandler: nil)
return false
}
Mettre à jour
Comme il openURL
est déconseillé dans iOS 10:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
if (navigationType == UIWebViewNavigationTypeLinkClicked ) {
UIApplication *application = [UIApplication sharedApplication];
[application openURL:[request URL] options:@{} completionHandler:nil];
return NO;
}
return YES;
}
switch
est préférable pour les types d'énumération
Si quelqu'un se demande, la solution de Drawnonward ressemblerait à ceci dans Swift :
func webView(webView: UIWebView!, shouldStartLoadWithRequest request: NSURLRequest!, navigationType: UIWebViewNavigationType) -> Bool {
if navigationType == UIWebViewNavigationType.LinkClicked {
UIApplication.sharedApplication().openURL(request.URL)
return false
}
return true
}
UIWebViewDelegate
Un petit commentaire sur la réponse de user306253: attention à cela, lorsque vous essayez de charger quelque chose dans UIWebView vous-même (c'est-à-dire même à partir du code), cette méthode empêchera que cela se produise.
Ce que vous pouvez faire pour éviter cela (merci Wade), c'est:
if (inType == UIWebViewNavigationTypeLinkClicked) {
[[UIApplication sharedApplication] openURL:[inRequest URL]];
return NO;
}
return YES;
Vous pouvez également gérer les types UIWebViewNavigationTypeFormSubmitted
et UIWebViewNavigationTypeFormResubmitted
.
Les autres réponses ont un problème: elles dépendent de l'action que vous effectuez et non du lien lui-même pour décider de le charger dans Safari ou dans la vue Web.
Maintenant, parfois, c'est exactement ce que vous voulez, ce qui est bien; mais d'autres fois, surtout si vous avez des liens d'ancrage dans votre page, vous voulez vraiment n'ouvrir que des liens externes dans Safari, et pas des liens internes. Dans ce cas, vous devez vérifier la URL.host
propriété de votre demande.
J'utilise ce morceau de code pour vérifier si j'ai un nom d'hôte dans l'URL en cours d'analyse, ou s'il est incorporé en html:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
static NSString *regexp = @"^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9-]*[a-zA-Z0-9])[.])+([A-Za-z]|[A-Za-z][A-Za-z0-9-]*[A-Za-z0-9])$";
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regexp];
if ([predicate evaluateWithObject:request.URL.host]) {
[[UIApplication sharedApplication] openURL:request.URL];
return NO;
} else {
return YES;
}
}
Vous pouvez bien sûr adapter l'expression régulière à vos besoins.
if (request.URL?.scheme != "file")
Dans Swift, vous pouvez utiliser le code suivant:
extension YourViewController: UIWebViewDelegate {
func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebView.NavigationType) -> Bool {
if let url = request.url, navigationType == UIWebView.NavigationType.linkClicked {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
return false
}
return true
}
}
Assurez-vous de vérifier la valeur de l'URL et le navigationType.
Voici l'équivalent Xamarin iOS de la réponse de drawonward.
class WebviewDelegate : UIWebViewDelegate {
public override bool ShouldStartLoad (UIWebView webView, NSUrlRequest request, UIWebViewNavigationType navigationType) {
if (navigationType == UIWebViewNavigationType.LinkClicked) {
UIApplication.SharedApplication.OpenUrl (request.Url);
return false;
}
return true;
}
}
La réponse acceptée ne fonctionne pas.
Si votre page charge des URL via Javascript, ce navigationType
sera le cas UIWebViewNavigationTypeOther
. Ce qui, malheureusement, inclut également des chargements de page d'arrière-plan tels que l'analyse.
Pour détecter la navigation dans les pages, vous devez comparer le [request URL]
à [request mainDocumentURL]
.
Cette solution fonctionnera dans tous les cas:
- (BOOL)webView:(UIWebView *)view shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)type
{
if ([[request URL] isEqual:[request mainDocumentURL]])
{
[[UIApplication sharedApplication] openURL:[request URL]];
return NO;
}
else
{
return YES;
}
}
Rejet de l'application Remarque:
Enfin UIWbView
est mort et Apple ne l'acceptera plus.
Apple a commencé à envoyer des e-mails à tous les propriétaires d'applications qui utilisent toujours UIWebView
:
Utilisation d'API obsolète - Apple cessera d'accepter les soumissions d'applications utilisant des UIWebView
API.
Apple prend la confidentialité des utilisateurs très au sérieux et il est évident qu'ils n'autoriseront pas la visualisation Web non sécurisée .
Supprimez donc UIWebView de votre application dès que possible. ne pas utiliser essayer d'utiliser UIWebView
dans une nouvelle application créée et je préfère utiliser WKWebView
si possible
ITMS-90809: Utilisation obsolète de l'API - Apple cessera d'accepter les soumissions d'applications qui utilisent les API UIWebView. Voir https://developer.apple.com/documentation/uikit/uiwebview pour plus d'informations.
Exemple:
import UIKit
import WebKit
class WebInfoController: UIViewController,WKNavigationDelegate {
var webView : WKWebView = {
var webview = WKWebView()
return webview
}()
var _fileName : String!
override func viewDidLoad() {
self.view.addSubview(webView)
webView.fillSuperview()
let url = Bundle.main.url(forResource: _fileName, withExtension: "html")!
webView.loadFileURL(url, allowingReadAccessTo: url)
let request = URLRequest(url: url)
webView.load(request)
}
func webView(webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: NSError) {
print(error.localizedDescription)
}
func webView(webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
print("Strat to load")
}
func webView(webView: WKWebView, didFinishNavigation navigation: WKNavigation!) {
print("finish to load")
}
}
Dans mon cas, je veux m'assurer qu'absolument tout dans la vue Web ouvre Safari sauf la charge initiale et donc j'utilise ...
- (BOOL)webView:(UIWebView *)inWeb shouldStartLoadWithRequest:(NSURLRequest *)inRequest navigationType:(UIWebViewNavigationType)inType {
if(inType != UIWebViewNavigationTypeOther) {
[[UIApplication sharedApplication] openURL:[inRequest URL]];
return NO;
}
return YES;
}