Safari'de UIWebView açık bağlantıları


304

Benim uygulama paketinden içerik ile çok basit bir UIWebView var. Web görünümünde herhangi bir bağlantının web görünümü yerine Safari'de açılmasını istiyorum. Mümkün mü?


Aşağıdaki kabul edilen cevap her durumda çalışmaz.
IanS

Daha iyi bir cevap ekledim. Lütfen cevabımı kabul edilen olarak işaretleyin.
IanS

Yanıtlar:


657

Bunu UIWebView temsilcisine ekleyin:

(gezinme türünü kontrol etmek için düzenlenmiştir. file://göreli bağlantılar olabilecek istekleri de aktarabilirsiniz )

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
    if (navigationType == UIWebViewNavigationTypeLinkClicked ) {
        [[UIApplication sharedApplication] openURL:[request URL]];
        return NO;
    }

    return YES;
}

Hızlı Sürüm:

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

Swift 3 sürümü:

func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool {
    if navigationType == UIWebViewNavigationType.linkClicked {
        UIApplication.shared.openURL(request.url!)
        return false
    }
    return true
}

Swift 4 sürümü:

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
}

Güncelleme

As openURLiOS 10'da kaldırıldı:

- (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;
}

drawonward, cevabınızı aşağıdaki cevap ve yorumlara referansla güncellemek ister misiniz?
Toby Allen

Kullanıcı tarayıcıyı kapattığında uygulamaya nasıl geri dönülür?
Johnny Everson

3
@ Jhonny Everson: Herhangi bir harici uygulama (Safari dahil) kapatıldıktan sonra ne olacağı konusunda hiçbir kontrole sahip değilsiniz. Kullanıcı göz atma işlemi tamamlandığında uygulamanıza geri dönmek istiyorsanız, Safari'yi açmayın, sadece UIWwbView ve "Bitti" düğmesini kullanın.
geon

1
Yerel HTML dosyası ile cazibe gibi çalıştı.
necixy

1
Bence Swift, a switchenum türleri için tercih edilebilir
SDJMcHattie

44

Birisi merak ederse, Drawnonward'ın çözümü Swift'te şöyle görünür :

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

bunu SADECE https: // http: // veya mailto :? swift kullanıyor musunuz? Burada soru hızlı bir cevap gerekiyor! stackoverflow.com/questions/2532453/…
Jed Grant

@JedGrant hızlı sürümü şimdi stackoverflow.com/questions/2532453/…
Carl Sharman

2
emin olunUIWebViewDelegate
Jay Mayu

28

User306253'ün cevabına hızlı bir yorum: UIWebView'e (yani koddan bile) bir şey yüklemeye çalıştığınızda, bununla dikkat edin, bu yöntem bunun olmasını önleyecektir.

Bunu önlemek için yapabileceğiniz (teşekkürler Wade):

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

return YES;

Ayrıca UIWebViewNavigationTypeFormSubmittedve UIWebViewNavigationTypeFormResubmittedtürlerini işlemek de isteyebilirsiniz .


8
+1 Aynı sorunu yaşadım. Çözüm, istek türü olarak UIWebViewNavigationTypeLinkClicked olup olmadığını kontrol etmekti, sonra URL'yi açın ve NO döndürün, aksi takdirde YES döndürün.
Wade Mueller

Wade yorumunuzu cevap olarak yazmalısınız
Toby Allen

16

Diğer cevapların bir sorunu var: Safari'de mi yoksa web görünümünde mi yükleyeceğinize karar vermek için bağlantının kendisine değil, yaptığınız eyleme güveniyorlar.

Şimdi bazen bu tam olarak istediğiniz şey, ki bu iyi; ancak diğer bazı zamanlarda, özellikle sayfanızda bağlantı bağlantıları varsa, Safari'de yalnızca dahili bağlantıları değil, yalnızca harici bağlantıları açmak istersiniz. Bu durumda URL.host, isteğinizin mülkünü kontrol etmelisiniz .

Ben ayrıştırılmakta olan URL'de bir ana bilgisayar adı olup olmadığını veya html gömülü olup olmadığını kontrol etmek için bu kod parçası kullanın:

- (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; 
    }
}

Elbette normal ifadeyi ihtiyaçlarınıza göre uyarlayabilirsiniz.



1
Evet, gelen istekleri filtreleme konusuna, ana makine adı ayrıştırmasına hayır. URL şemasına göre filtre uygulamak daha iyi bir yaklaşım olacaktır. İOS 8.4'te (simülatör), bağlantı bağlantıları için şema olarak "applewebdata" kullanıldım, ancak bu hedef sürüme göre değişebilir.
MandisaW

İyi fikir MandisaW. Ankraj bağlantılarına izin vermek için "dosya" şemasını kontrol ediyorumif (request.URL?.scheme != "file")
David Douglas

7

Swift'te aşağıdaki kodu kullanabilirsiniz:

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
    }

}

URL değerini ve navigationType öğesini kontrol ettiğinizden emin olun.


1

İşte drawnonward'ın cevabının Xamarin iOS eşdeğeri.

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

Kabul edilen cevap çalışmıyor.

Javascript aracılığıyla sayfa yüklendiğinde URL'ler, varsa navigationTypeolacak UIWebViewNavigationTypeOther. Maalesef, analitik gibi arka plan sayfa yüklerini de içerir.

Sayfa navigasyonu algılamak için, karşılaştırmak gerek [request URL]için [request mainDocumentURL].

Bu çözüm her durumda işe yarar:

- (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
Bunun Swift 4 versiyonunu gönderebilir misiniz?
Amjad

1

Uygulama reddi Not:

Sonunda UIWbViewöldü ve Apple artık kabul etmeyecek.

Apple, halen kullanılmakta olan tüm Uygulama sahibine e-posta göndermeye başladı UIWebView:

Kullanımdan Kaldırılmış API Kullanımı - Apple, API kullanan uygulamaların gönderilmesini kabul etmeyecek UIWebView.

Apple, Kullanıcı Gizliliğini çok ciddiye almaktadır ve güvenli olmayan web görüntülemesine izin vermeyecekleri açıktır .

Bu yüzden mümkün olan en kısa sürede UIWebView uygulamasını uygulamanızdan kaldırın. UIWebViewyeni oluşturulan uygulamada kullanmayı deneyin ve WKWebViewmümkünse kullanmayı tercih ederim

ITMS-90809: Kullanımdan Kaldırılmış API Kullanımı - Apple, UIWebView API'lerini kullanan uygulamaların gönderilmesini kabul etmeyecek. Daha fazla bilgi için https://developer.apple.com/documentation/uikit/uiwebview adresine bakın .

Misal:

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")
    }
}

0

Benim durumumda, web görünümündeki her şeyin ilk yükleme dışında Safari'yi açtığından emin olmak istiyorum ve bu yüzden kullanıyorum ...

- (BOOL)webView:(UIWebView *)inWeb shouldStartLoadWithRequest:(NSURLRequest *)inRequest navigationType:(UIWebViewNavigationType)inType {
     if(inType != UIWebViewNavigationTypeOther) {
        [[UIApplication sharedApplication] openURL:[inRequest URL]];
        return NO;
     }
     return YES;
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.