Eu tenho um UIWebView muito simples com conteúdo do meu pacote de aplicativos. Gostaria que todos os links na visualização da Web fossem abertos no Safari em vez de na visualização da Web. Isso é possível?
Eu tenho um UIWebView muito simples com conteúdo do meu pacote de aplicativos. Gostaria que todos os links na visualização da Web fossem abertos no Safari em vez de na visualização da Web. Isso é possível?
Respostas:
Adicione isso ao delegado UIWebView:
(editado para verificar o tipo de navegação. você também pode passar por file://
solicitações que seriam links relativos)
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
if (navigationType == UIWebViewNavigationTypeLinkClicked ) {
[[UIApplication sharedApplication] openURL:[request URL]];
return NO;
}
return YES;
}
Versão rápida:
func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {
if navigationType == UIWebViewNavigationType.LinkClicked {
UIApplication.sharedApplication().openURL(request.URL!)
return false
}
return true
}
Versão 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
}
Versão 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
}
Atualizar
Como openURL
foi preterido no 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
é preferível para tipos de enum
Se alguém se perguntar, a solução de Drawnonward seria assim em 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
Um comentário rápido à resposta do usuário306253: cuidado com isso, quando você tenta carregar algo no UIWebView por conta própria (ou seja, mesmo a partir do código), esse método impedirá que isso aconteça.
O que você pode fazer para evitar isso (obrigado Wade) é:
if (inType == UIWebViewNavigationTypeLinkClicked) {
[[UIApplication sharedApplication] openURL:[inRequest URL]];
return NO;
}
return YES;
Você também pode querer lidar com os tipos UIWebViewNavigationTypeFormSubmitted
e UIWebViewNavigationTypeFormResubmitted
.
As outras respostas têm um problema: elas dependem da ação que você executa e não no próprio link para decidir se o carregam no Safari ou na visualização na web.
Agora, às vezes, é exatamente isso que você deseja, o que é bom; mas outras vezes, especialmente se você tiver links âncora em sua página, você deseja realmente abrir apenas links externos no Safari, e não internos. Nesse caso, você deve verificar a URL.host
propriedade da sua solicitação.
Eu uso esse trecho de código para verificar se tenho um nome de host na URL que está sendo analisada ou se ele está incorporado em 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;
}
}
Obviamente, você pode adaptar a expressão regular para atender às suas necessidades.
if (request.URL?.scheme != "file")
No Swift, você pode usar o seguinte código:
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
}
}
Verifique o valor da URL e o navigationType.
Aqui está o equivalente do Xamarin iOS à resposta do 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;
}
}
A resposta aceita não funciona.
Se sua página carregar URLs via Javascript, navigationType
será UIWebViewNavigationTypeOther
. Que, infelizmente, também inclui carregamentos de páginas em segundo plano, como análises.
Para detectar a navegação da página, você precisa comparar [request URL]
com o [request mainDocumentURL]
.
Esta solução funcionará em todos os casos:
- (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;
}
}
Rejeição de aplicativo Nota:
Finalmente UIWbView
está morto e a Apple não aceitará mais.
A Apple começou a enviar e-mails para todo o proprietário do aplicativo que ainda está usando UIWebView
:
Uso preterido da API - a Apple deixará de aceitar envios de aplicativos que usam UIWebView
APIs.
A Apple leva a privacidade do usuário muito a sério e é óbvio que eles não permitirão visualizações inseguras da web .
Portanto, remova o UIWebView do seu aplicativo o mais rápido possível. não use tente usar UIWebView
no novo aplicativo criado e eu prefiro usar WKWebView
se possível
ITMS-90809: Uso preterido da API - a Apple deixará de aceitar envios de aplicativos que usam APIs UIWebView. Consulte https://developer.apple.com/documentation/uikit/uiwebview para obter mais informações.
Exemplo:
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")
}
}
No meu caso, quero garantir que absolutamente tudo na visualização da Web abra o Safari, exceto o carregamento inicial e, portanto, uso ...
- (BOOL)webView:(UIWebView *)inWeb shouldStartLoadWithRequest:(NSURLRequest *)inRequest navigationType:(UIWebViewNavigationType)inType {
if(inType != UIWebViewNavigationTypeOther) {
[[UIApplication sharedApplication] openURL:[inRequest URL]];
return NO;
}
return YES;
}