UIWebView ouvrir des liens dans Safari

J'ai un UIWebView très simple avec le contenu de mon paquet d'applications. Je voudrais que tous les liens du web pour l'ouvrir dans Safari au lieu de dans la vue web. Est-ce possible?

292
demandé sur Wayne Chen 2010-05-24 23:32:11

8 réponses

Ajoutez ceci au délégué UIWebView:

(modifié pour vérifier le type de navigation. vous pouvez également passer par file:// requêtes 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 Swift:

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
}

mise à Jour

Comme openURL a été obsolète 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;
}
640
répondu drawnonward 2017-03-18 15:36:18

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
}
43
répondu DiegoFrings 2014-10-08 08:31:10

Un commentaire rapide à la réponse de user306253: attention, 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 cela.

Ce que vous pouvez faire pour éviter cela (merci Wade) est:

if (inType == UIWebViewNavigationTypeLinkClicked) {
    [[UIApplication sharedApplication] openURL:[inRequest URL]];
    return NO;
}

return YES;

, Vous pouvez également gérer les UIWebViewNavigationTypeFormSubmitted et UIWebViewNavigationTypeFormResubmitted types.

28
répondu MonsieurDart 2011-03-24 10:03:53

Les autres réponses ont un problème: elles s'appuient sur l'action que vous faites et non sur le lien lui-même pour décider de le charger dans Safari ou dans webview.

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 ouvrir uniquement des liens externes dans Safari, et non des liens internes. Dans ce cas, vous devriez vérifier la propriété URL.host de votre demande.

J'utilise ce morceau de code pour vérifier si je avoir un nom d'hôte dans L'URL qui est en cours d'analyse, ou s'il est intégré 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.

15
répondu KPM 2012-10-02 21:32:17

Dans Swift, vous pouvez utiliser le code suivant:

extension YourViewController : UIWebViewDelegate {
    func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {
        if let url = request.URL where navigationType == UIWebViewNavigationType.LinkClicked {
            UIApplication.sharedApplication().openURL(url)
            return false
        }
        return true
    }
}

Assurez-vous de vérifier la valeur de L'URL et le navigationType.

7
répondu Antoine 2015-09-16 11:25:20

Voici L'équivalent Xamarin iOS de la réponse de drawnonward.

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;
    }
}
1
répondu danfordham 2016-01-10 15:12:15

La réponse acceptée ne fonctionne pas.

Si votre page charge des URL via Javascript, le {[1] } sera UIWebViewNavigationTypeOther. Qui, malheureusement, comprend également des charges de page d'arrière-plan telles que l'analyse.

Pour détecter la navigation de page, vous devez comparer le [request URL] au [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;
    }
}
1
répondu IanS 2016-06-29 14:45:03

Dans mon cas, je veux m'assurer que 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;
}
0
répondu Michael Platt 2014-12-05 11:18:55