WKWebView लक्ष्य = "रिक्त" के साथ लिंक क्यों नहीं खोल रहा है?


122

WKWebViewtarget="_blank"अपने HTML <a href>-Tag में कोई लिंक नहीं खोलते हैं जो उर्फ 'नई विंडो में खोलें' विशेषता है ।


कृपया सही उत्तर को चिह्नित करें
एफ्रेन

जवाबों:


184

मेरा समाधान नेविगेशन को रद्द करना और लोडरकेस के साथ अनुरोध को लोड करना है: फिर से। यह UIWebView के समान व्यवहार आएगा जो हमेशा वर्तमान फ्रेम में नई विंडो खोलते हैं।

WKUIDelegateप्रतिनिधि को लागू करें और इसे सेट करें _webview.uiDelegate। फिर लागू करें:

- (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures
{
  if (!navigationAction.targetFrame.isMainFrame) {
    [webView loadRequest:navigationAction.request];
  }

  return nil;
}

4
यह सही जवाब है। हमने बिना किसी सफलता के स्वीकार किए गए उत्तर की कोशिश की। लेकिन @ क्लाउड का जवाब काम करता है, और देव मंचों पर यह प्रतिक्रिया बताती है कि क्यों।
क्रिस्टोफर पिक्सले

5
इस समाधान ने मेरे लिए काम किया। UIDelegateसंपत्ति सेट करना न भूलें , क्योंकि यह विधियाँ घोषित WKUIDelegateनहीं की गई हैं WKNavigationDelegate
टैकटो सानो

1
ठीक है, मैं देखता हूं कि लोग इस तरह WKWebView का उपयोग करना चाहते हैं। मैंने अपनी परियोजना github.com/sticksen/STKWebKitViewController में समान WKWebView में (जैसा कि ऊपर दिखाया गया है) लक्ष्य = _blank- लिंक खोलने की संभावना को लागू किया ।
स्टक

5
@ WKWebView के साथ इस विधि का उपयोग करते समय @ChristopherPickslay हमेशा आग्रह करता है कि रिक्त है, इसलिए वेबव्यू एक खाली सफेद पृष्ठ पर निर्देशित करता है, कोई विचार?
जेसन मरे

1
जब '_blank' अनुरोध पोस्ट डेटा के साथ एक फॉर्म से भेजा जाता है, तो मुझे लगता है कि पोस्ट डेटा खो जाएगा !!! कोई मदद? @ क्लॉउड वू
एंड्रयू

66

@ क्लॉड जू का जवाब सही उत्तर है। बस संदर्भ के लिए, यहाँ यह स्विफ्ट में है:

// this handles target=_blank links by opening them in the same view
func webView(webView: WKWebView!, createWebViewWithConfiguration configuration: WKWebViewConfiguration!, forNavigationAction navigationAction: WKNavigationAction!, windowFeatures: WKWindowFeatures!) -> WKWebView! {
    if navigationAction.targetFrame == nil {
        webView.loadRequest(navigationAction.request)
    }
    return nil
}

2
यदि आप इसे सफारी में खोलना चाहते हैं तो आप इसे कैसे लिखेंगे? यह देखने के लिए कि मुझे यह काम करने के लिए व्यू कंट्रोलर में क्या चाहिए?
जेड ग्रांट

1
मोबाइल सफारी में खोलने के लिए नया पेज पाने के लिए, इस उत्तर को देखें: stackoverflow.com/a/30604481/558789
पॉल ब्रूनो

1
यह लिंक के लिए काम करता है, लेकिन जावास्क्रिप्ट के साथ खोली गई नई खिड़कियों का पता नहीं लगता है, अर्थात, window.open (url, "_blank")
Crashalot

FYI करें webView.loadRequest को जाहिरा तौर पर API के हाल के संस्करणों में webView.load का नाम दिया गया है
बिल वेनमैन

52

स्विफ्ट के नवीनतम संस्करण का उपयोग करने के लिए 4.2+

import WebKit

WKUIDelegate के साथ अपनी कक्षा बढ़ाएँ

Webview के लिए प्रतिनिधि सेट करें

self.webView.uiDelegate = self

प्रोटोकॉल विधि को लागू करें

func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
    if navigationAction.targetFrame == nil {
        webView.load(navigationAction.request)
    }
    return nil
}

असली डुप्लिकेट नहीं। आपके द्वारा लिंक किए गए उत्तर में स्विफ्ट 4.1 WKUIDelegate प्रोटोकॉल के अनुरूप नहीं होने वाले मापदंडों की वैकल्पिकता में अंतर हैं।
याकट्टैक

नमस्ते, जब मैं Pinterest URL के साथ WKWebview लोड कर रहा हूं, तो मैं "फेसबुक के साथ जारी रखें" खोलने में असमर्थ था। अब मैं "कंटीन्यू विद गूगल" पर क्लिक कर जानकारी प्राप्त कर सकता हूँ। कृपया मेरी मदद करें।
Nrv

मैं wkwebview के साथ एक ही मुद्दे का सामना कर रहा हूं; लॉगिन और रीडायरेक्ट मेरे ऐप में काम नहीं किया। कोई मदद ?
जमशेद आलम

1
कृपया किसी को भी मेरी मदद कर सकते हैं, मैं प्रतिनिधि uiDelegate wkwebview को सौंपा है, लेकिन इसकी विधि विन्यास के साथ वेब दृश्य बनाने के लिए नहीं बुलाया जा रहा है
चेतन पांचाल

25

WKNavigationDelegate के रूप में खुद को जोड़ें

_webView.navigationDelegate = self;

और प्रतिनिधि कॉलबैक निश्चय में निम्नलिखित कोड लागू करें

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
    //this is a 'new window action' (aka target="_blank") > open this URL externally. If we´re doing nothing here, WKWebView will also just do nothing. Maybe this will change in a later stage of the iOS 8 Beta
    if (!navigationAction.targetFrame) { 
        NSURL *url = navigationAction.request.URL;
        UIApplication *app = [UIApplication sharedApplication];
        if ([app canOpenURL:url]) {
            [app openURL:url];
        }
    }
    decisionHandler(WKNavigationActionPolicyAllow);
}

PS: यह कोड मेरी छोटी परियोजना से है STKWebKitViewController, जो WKWebView के चारों ओर प्रयोग करने योग्य UI को लपेटता है।


1
एक टाइपो है। WKNavigationActionPolicy और अनुमति के बीच एक बिंदु गायब है
चिकन 16

@stk यदि UIApplication Safari ऐप में लिंक खोलने जा रहा है तो मैं कैसे समझ सकता हूं? यदि यह Appstore लिंक है - मुझे Appstore ऐप में ओ.टी. खोलने की आवश्यकता है, लेकिन अगर यह सामान्य वेब पेज है - तो मुझे इसे उसी WKWebView stackoverflow.com/questions/29056854//
BergP

1
@LeoKoppelkamm यह टाइपो नहीं है बल्कि यह ऑब्जेक्टिव-सी स्विफ्ट नहीं है। ;)
अयान सेनगुप्ता

1
यह लिंक के लिए काम करता है, लेकिन जावास्क्रिप्ट के साथ खोली गई नई खिड़कियों का पता नहीं लगता है, यानीwindow.open(url, "_blank")
Crashalot

@Crashalot क्या आपने window.open का हल खोजा?
सैम

14

यदि आप WKWebView.navigationDelegate पहले ही सेट कर चुके हैं

WKWebView.navigationDelegate = self;

आपको बस लागू करने की आवश्यकता है:

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
    BOOL shouldLoad = [self shouldStartLoadWithRequest:navigationAction.request]; // check the url if necessary

    if (shouldLoad && navigationAction.targetFrame == nil) {
        // WKWebView ignores links that open in new window
        [webView loadRequest:navigationAction.request];
    }

    // always pass a policy to the decisionHandler
    decisionHandler(shouldLoad ? WKNavigationActionPolicyAllow : WKNavigationActionPolicyCancel);
}

इस तरह आपको WKUIDelegate पद्धति को लागू करने की आवश्यकता नहीं है।


1
यह लिंक के लिए काम करता है, लेकिन जावास्क्रिप्ट के साथ खोली गई नई खिड़कियों का पता नहीं लगता है, अर्थात, window.open (url, "_blank")
Crashalot

@ चरसालोट क्या आपने इस उत्तर की जाँच की है? stackoverflow.com/questions/33190234/wkwebview-and-window-open
जोस रेगो

8

उन समाधानों में से किसी ने भी मेरे लिए काम नहीं किया, मैंने इस मुद्दे को हल किया:

1) WKUIDelegate लागू करना

@interface ViewController () <WKNavigationDelegate, WKUIDelegate>

2) wkWebview के UIDelegate प्रतिनिधि की स्थापना

self.wkWebview.UIDelegate = self;

3) createWebViewWithConfiguration विधि को लागू करना

- (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures {

if (!navigationAction.targetFrame.isMainFrame) {
    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
    [[UIApplication sharedApplication] openURL:[navigationAction.request URL]];
}
return nil;  }

मुझे ऐसा करते समय सिर्फ एक SIGABRT मिलता है। यह काम नहीं करता है।
user2009449

8

Cloud xuजवाब मेरा मुद्दा हल करती है।

यदि किसी को समकक्ष स्विफ्ट (4.x / 5.0) संस्करण की आवश्यकता है, तो यह है:

func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
    if let frame = navigationAction.targetFrame,
        frame.isMainFrame {
        return nil
    }
    // for _blank target or non-mainFrame target
    webView.load(navigationAction.request)
    return nil
}

बेशक आपको webView.uiDelegateसबसे पहले सेट करना होगा ।


7

मैं पुष्टि करता हूं कि बिल वेनमैन का स्विफ्ट कोड सही है। लेकिन यह उल्लेख करने की आवश्यकता है कि आपको भी काम करने के लिए UIDelegate को सौंपना होगा, यदि आप मेरे जैसे iOS के विकास के लिए नए हैं।

कुछ इस तरह:

self.webView?.UIDelegate = self

इसलिए तीन जगह हैं जिन्हें आपको बदलाव करने की आवश्यकता है।


अपने कोड में टाइप करें, यह है:self.webView.UIDelegate = self
हेनरिक पेटर्सन

यकीन नहीं है कि यह निहित है, लेकिन iOS 10 में काम करने के लिए कोड की इस पंक्ति के लिए आपको ViewControllerविरासत में चाहिए WKUIDelegate। यानीclass ViewController: UIViewController, WKNavigationDelegate, WKScriptMessageHandler, WKUIDelegate
ltrainpr

4

आप किसी अन्य दृश्य नियंत्रक को भी धक्का दे सकते हैं, या एक नया टैब खोल सकते हैं, आदि:

func webView(webView: WKWebView, createWebViewWithConfiguration configuration: WKWebViewConfiguration, forNavigationAction navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
    var wv: WKWebView?

    if navigationAction.targetFrame == nil {
        if let vc = self.storyboard?.instantiateViewControllerWithIdentifier("ViewController")  as? ViewController {
            vc.url = navigationAction.request.URL
            vc.webConfig = configuration
            wv = vc.view as? WKWebView

            self.navigationController?.pushViewController(vc, animated: true)
        }
    }

    return wv
}

क्या इसे सेट करना आवश्यक है vc.url? मैं इसे सेट नहीं कर रहा हूं, और वेब दृश्य ठीक से लोड हो रहा है। इसके अलावा, मेरे अनुभव में मैं केवल यह देख रहा हूं कि createWebViewWithConfigurationकब क्या navigationAction.targetFrameहै nil। क्या आप ऐसे परिदृश्य का वर्णन कर सकते हैं जहाँ यह सच नहीं होगा?
मेसन जी। ज़िविती

@ MasonG.Zhwiti मैं पिछले एक परियोजना के लिए सक्रिय रूप से WKWebViews का उपयोग कर रहा था, लेकिन तब से उनके साथ कुछ भी नहीं किया है - इसलिए मैं वास्तव में आपके प्रश्न का उत्तर नहीं दे सकता। जिस समय मैंने ऊपर पोस्ट किया था उस समय यह काम किया था। मैं थाह नहीं कर सकता कि यह vc.url को सेट किए बिना कैसे काम करता है।
डेविड एच।

मुझे लगता है कि यह आपके बिना काम करता है क्योंकि आप अपने द्वारा बनाए गए वेब दृश्य को वापस कर रहे हैं, और तब (मैं अनुमान लगा रहा हूं) जो कुछ भी आपने इसे बनाने के लिए कहा है वह प्रश्न में URL को लोड करने के लिए वेब दृश्य का उपयोग करने का ख्याल रखता है।
मेसन जी। ज़्विती

3

एलन हुआंग जवाब के आधार पर

विवरण

  • Xcode संस्करण 10.3 (10G8), स्विफ्ट 5

लक्ष्य

  • के साथ लिंक का पता लगाएं target=“_blank”
  • push यदि वर्तमान नियंत्रक है, तो वेब व्यू के साथ कंट्रोलर देखें navigationController
  • present अन्य सभी मामलों में वेब व्यू के साथ कंट्रोलर देखें

उपाय

webView.uiDelegate = self

// .....

extension ViewController: WKUIDelegate {
    func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
        guard   navigationAction.targetFrame == nil,
                let url =  navigationAction.request.url else { return nil }
        let vc = ViewController(url: url, configuration: configuration)
        if let navigationController = navigationController {
            navigationController.pushViewController(vc, animated: false)
            return vc.webView
        }
        present(vc, animated: true, completion: nil)
        return nil
    }
}

पूरा नमूना

Info.plist

अपने Info.plist परिवहन सुरक्षा सेटिंग में जोड़ें

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

ViewController

import UIKit
import WebKit

class ViewController: UIViewController {

    private lazy var url = URL(string: "https://www.w3schools.com/html/tryit.asp?filename=tryhtml_links_target")!
    private weak var webView: WKWebView!

    init (url: URL, configuration: WKWebViewConfiguration) {
        super.init(nibName: nil, bundle: nil)
        self.url = url
        navigationItem.title = ""
    }

    required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }

    override func viewDidLoad() {
        super.viewDidLoad()
        initWebView()
        webView.loadPage(address: url)
    }

    private func initWebView() {
        let webView = WKWebView(frame: .zero, configuration: WKWebViewConfiguration())
        view.addSubview(webView)
        self.webView = webView
        webView.navigationDelegate = self
        webView.uiDelegate = self
        webView.translatesAutoresizingMaskIntoConstraints = false
        webView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
        webView.rightAnchor.constraint(equalTo: view.safeAreaLayoutGuide.rightAnchor).isActive = true
        webView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
        webView.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor).isActive = true
    }
}

extension ViewController: WKNavigationDelegate {
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        guard let host = webView.url?.host else { return }
        navigationItem.title = host
    }
}

extension ViewController: WKUIDelegate {
    func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
        guard   navigationAction.targetFrame == nil,
                let url =  navigationAction.request.url else { return nil }
        let vc = ViewController(url: url, configuration: configuration)
        if let navigationController = navigationController {
            navigationController.pushViewController(vc, animated: false)
            return vc.webView
        }
        present(vc, animated: true, completion: nil)
        return nil
    }
}

extension WKWebView {
    func loadPage(address url: URL) { load(URLRequest(url: url)) }
    func loadPage(address urlString: String) {
        guard let url = URL(string: urlString) else { return }
        loadPage(address: url)
    }
}

स्टोरीबोर्ड

संस्करण 1

यहां छवि विवरण दर्ज करें

संस्करण 2

यहां छवि विवरण दर्ज करें


नमस्ते, फेसबुक के साथ लॉगिन करने के बाद, उसी तरह से फेसबुक के लिए शेयर विंडो कैसे खोलें? मैंने नया wkwebview बनाने के साथ लॉगिन किया है, अब उपयोगकर्ता लॉग इन है। अब शेयर विंडो कैसे ट्रैक करें?
जमशेद आलम

धन्यवाद, आपका समाधान मेरे जीवन को बचाए
रखता है

2

यह मेरे लिए काम किया:

-(WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures {

if (!navigationAction.targetFrame.isMainFrame) {


    WKWebView *newWebview = [[WKWebView alloc] initWithFrame:self.view.frame configuration:configuration];
    newWebview.UIDelegate = self;
    newWebview.navigationDelegate = self;
    [newWebview loadRequest:navigationAction.request];
    self.view = newWebview;

    return  newWebview;
}

return nil;
}

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {

    decisionHandler(WKNavigationActionPolicyAllow);
}

- (void)webViewDidClose:(WKWebView *)webView {
    self.view = self.webView;
}

जैसा कि आप देख सकते हैं, हम यहां जो कुछ भी कर रहे हैं, वह केवल webViewनए url के साथ एक नया खोल रहा है और बंद होने की सकारात्मकता को नियंत्रित कर रहा है, बस अगर आपको second webviewपहले से प्रदर्शित होने के लिए उस से प्रतिक्रिया की आवश्यकता है ।


1

मुझे कुछ मुद्दों का सामना करना पड़ा, जिन्हें केवल उपयोग करके हल नहीं किया जा सकता है webView.load(navigationAction.request)। इसलिए मैं एक नया वेबव्यू बनाने के लिए उपयोग करता हूं और यह ठीक काम करता है।

//MARK:- WKUIDelegate
func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
    NSLog(#function)

    if navigationAction.targetFrame == nil {
        NSLog("=> Create a new webView")

        let webView = WKWebView(frame: self.view.bounds, configuration: configuration)
        webView.uiDelegate = self
        webView.navigationDelegate = self

        self.webView = webView

        return webView
    }
    return nil
}

0
**Use following function to create web view**

func initWebView(configuration: WKWebViewConfiguration) 
{
        let webView = WKWebView(frame: UIScreen.main.bounds, configuration: configuration)
        webView.uiDelegate = self
        webView.navigationDelegate = self
        view.addSubview(webView)
        self.webView = webView
    }

**In View Did Load:**

 if webView == nil { initWebView(configuration: WKWebViewConfiguration()) }
   webView?.load(url: url1)


**WKUIDelegate Method need to be implemented**

extension WebViewController: WKUIDelegate {

    func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
        // push new screen to the navigation controller when need to open url in another "tab"
        print("url:\(String(describing: navigationAction.request.url?.absoluteString))")
        if let url = navigationAction.request.url, navigationAction.targetFrame == nil {
            let viewController = WebViewController()
            viewController.initWebView(configuration: configuration)
            viewController.url1 = url
            DispatchQueue.main.async { [weak self] in
                self?.navigationController?.pushViewController(viewController, animated: true)
            }
            return viewController.webView
        }

        return nil
    }
}

extension WKWebView 

{
    func load(url: URL) { load(URLRequest(url: url)) }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.