2008-11-06 13 views
7

के उदाहरण में जावास्क्रिप्ट लिंक खुल रहा है, मैं वेबकिट का उपयोग करके एक मूलभूत कोको एप्लिकेशन बना रहा हूं, इसमें फ्लैश/सिल्वरलाइट एप्लिकेशन प्रदर्शित करने के लिए। बहुत ही बुनियादी, ब्राउज़र के लिए स्वयं के लिए कोई इरादा नहीं है।कोको/वेबकिट, जिसमें "window.open()" सफारी

अब तक मैं

[[NSWorkspace sharedWorkspace] openURL:[request URL]]; 

अब मेरी कठिनाई सफारी की जब window.open() एक नया उदाहरण में एक कड़ी खोल रहा है का उपयोग कर सफारी का एक नया उदाहरण में मूल HTML लिंक (<a href="..." />) खोलने के लिए इसे पाने के लिए सक्षम किया गया है जावास्क्रिप्ट में प्रयोग किया जाता है। मैं "लगता है कि" (और इस से, मैं कोड पर दूर हैकिंग किया गया है और अनिश्चित अगर मैं वास्तव में है या नहीं किया हूँ) मैं WebView के policyDelegate स्थापित करने और अपने

-webView:decidePolicyForNavigationAction:request:frame:decisionListener: 

प्रतिनिधि विधि को लागू करने से काम कर रहे इस तरह का हो गया । हालांकि इससे कुछ अनियमित व्यवहार हुआ।

तो सरल सवाल है, क्या मुझे लगता है कि जब window.open() कहा जाता है, लिंक सफारी का एक नया उदाहरण में खोला जाता है ऐसा करने की आवश्यकता है।

धन्यवाद

बिग बिंदु, मैं सामान्य रूप से एक .NET डेवलपर हूँ, और केवल कुछ ही दिनों के लिए कोको/WebKit के साथ काम कर रहा है।

+0

मुझे एक ही समस्या है। ऐसा लगता है कि यह एक बग है कि 'वेब व्यू: तय करें पॉलिसीफॉरन्यूविंडोएक्शन: अनुरोध: नया फ्रेम नाम: निर्णय लिस्टर' नहीं कहा जाता है। –

उत्तर

2

आप इस बात का जिक्र नहीं करते कि आप किस तरह का अनियमित व्यवहार देख रहे हैं। एक त्वरित संभावना यह है कि प्रतिनिधि विधि को लागू करते समय आप वेबव्यू को बताना भूल गए थे, आप WebPolicyDecisionListener की अनदेखी विधि को कॉल करके क्लिक को अनदेखा कर रहे हैं जो आपके प्रतिनिधि को पास कर दिया गया था, जो चीजों को अजीब स्थिति में डाल सकता है।

यदि यह समस्या नहीं है, तो आपके द्वारा प्रदर्शित सामग्री पर आपके पास कितना नियंत्रण है? पॉलिसी प्रतिनिधि आपको सभी संसाधन भारों को फ़िल्टर करने के लिए आसान तंत्र प्रदान करता है (जैसा कि आपने पाया है), और सभी नई विंडो webView:decidePolicyForNewWindowAction:request:newFrameName:decisionListener: के माध्यम से खुलती हैं। सभी window.open कॉलों को उस के माध्यम से फ़नल करना चाहिए, जैसा कि कोई और नई विंडो ट्रिगर करेगा।

यदि अन्य विंडो खुलती हैं तो आप अपने ऐप के अंदर रखना चाहते हैं, तो आप थोड़ा और काम करेंगे। प्रतिनिधि में पारित तर्कों में से एक घटना के बारे में information युक्त एक शब्दकोश है। Insie कि WebActionElementKey शब्दकोश में एक शब्दकोश होगा जिसमें लिंक की मूल डोम सामग्री सहित details की एक शब्दकोश होगी। यदि आप वहां चारों ओर पोक करना चाहते हैं तो आप वास्तविक डीओएम तत्व को पकड़ सकते हैं, और यह देखने के लिए href के टेक्स्ट को जांच सकते हैं कि यह window.open से शुरू होता है या नहीं। यह थोड़ा भारी वजन है, लेकिन यदि आप ठीक दाग नियंत्रण चाहते हैं तो यह आपको देगा।

+0

आपके लिए फीडबैक लुईस के लिए धन्यवाद, मैंने पिछले दो लिंक में चेक किया है, और मैंने उन्हें देखा है, दुर्भाग्य से मुझे नहीं लगता कि यह काम करेगा क्योंकि window.open एक एंकर टैग के भीतर इनलाइन नहीं है। इसे जावास्क्रिप्ट विधि के माध्यम से बुलाया जाता है जिसे सिल्वरलाइट से बुलाया जाता है। – FireWire

9

मैंने कल रात प्रगति की और मेरी समस्या का हिस्सा नीचे पिन किया।

मैं पहले से ही webView:decidePolicyForNewWindowAction:request:newFrameName:decisionListener: का उपयोग कर रहा हूं और मुझे इसे एंकर टैग के साथ काम करने के लिए मिला है, हालांकि जावास्क्रिप्ट को लागू होने पर विधि को कभी भी कॉल नहीं किया जाता है।

हालांकि window.open() को webView:createWebViewWithRequest:request कहा जाता है, मैंने सफारी में खिड़की को खोलने के लिए मजबूर करने की कोशिश की है, हालांकि अनुरोध हमेशा शून्य है। तो मैं यूआरएल को कभी नहीं पढ़ सकता।

मैंने कुछ खोज किया है, और यह एक ज्ञात "दुरूपयोग" लगता है, हालांकि मैं इसके आसपास काम करने का कोई तरीका नहीं ढूंढ पाया।

जो मैं समझता हूं उससे createWebViewWithRequest आपको नया वेबदृश्य बनाने की क्षमता देता है, अनुरोधित यूआरएल को लोड होने के लिए नए वेब व्यू पर भेजा जाता है। This is the best explanation I have been able to find so far.

इसलिए कई लोगों ने इस समस्या को इंगित किया है, लेकिन मुझे अभी तक कोई समाधान नहीं दिख रहा है जो मेरी आवश्यकताओं के अनुरूप है। मैं decidePolicyForNewWindowAction में थोड़ा गहराई से डेल करने की कोशिश करूंगा।

धन्यवाद!

+0

यह बहुत उपयोगी है। महान काम, आदमी! :) – Kimpoy

6

ठीक है, मैं, एक डमी WebView बनाकर उसका रख-रखाव कर रहा हूँ तो उसे सेट कि

- (void)webView:decidePolicyForNavigationAction:actionInformation :request:frame:decisionListener: 

संभालती है और वहाँ एक नई विंडो खोलता है एक कस्टम वर्ग के लिए frameLoad प्रतिनिधि है।

कोड:

- (WebView *)webView:(WebView *)sender createWebViewWithRequest:(NSURLRequest *)request { 
    //this is a hack because request URL is null here due to a bug in webkit   
    return [newWindowHandler webView]; 
} 

और NewWindowHandler:

@implementation NewWindowHandler 

-(NewWindowHandler*)initWithWebView:(WebView*)newWebView { 
    webView = newWebView; 

    [webView setUIDelegate:self]; 
    [webView setPolicyDelegate:self]; 
    [webView setResourceLoadDelegate:self]; 

    return self; 
} 

- (void)webView:(WebView *)sender decidePolicyForNavigationAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request frame:(WebFrame *)frame decisionListener:(id<WebPolicyDecisionListener>)listener { 
    [[NSWorkspace sharedWorkspace] openURL:[actionInformation objectForKey:WebActionOriginalURLKey]]; 
} 

-(WebView*)webView { 
    return webView; 
} 
4

उस में webView:decidePolicyForNewWindowAction:request:newFrameName:decisionListener: साथ एक बग अनुरोध हमेशा nil है प्रतीत हो रहा है, लेकिन वहाँ एक मजबूत समाधान है कि दोनों सामान्य के साथ काम करता है target="_blank" लिंक के साथ ही जावास्क्रिप्ट वाले।

मूल रूप से मैं नए पृष्ठ लोड को संभालने के लिए एक और क्षणिक वेबव्यू का उपयोग करता हूं। योनी शालोम की तरह, लेकिन थोड़ी अधिक वाक्य रचनात्मक चीनी के साथ।

यह पहली बार इस मामले में, अपने WebView के लिए एक प्रतिनिधि ऑब्जेक्ट सेट मैं अपने आप को प्रतिनिधि के रूप में सेट कर रहा हूं उपयोग करने के लिए:

webView.UIDelegate = self; 

तो बस webView:createWebViewWithRequest: प्रतिनिधि विधि को लागू करने और मेरी ब्लॉक आधारित एपीआई का उपयोग करने के लिए कुछ नया पृष्ठ लोड होने पर, इस मामले में मैं एक बाहरी ब्राउज़र में पृष्ठ खोल रहा हूं:

-(WebView *)webView:(WebView *)sender createWebViewWithRequest:(NSURLRequest *)request { 
    return [GBWebViewExternalLinkHandler riggedWebViewWithLoadHandler:^(NSURL *url) { 
     [[NSWorkspace sharedWorkspace] openURL:url]; 
    }]; 
} 

यह बहुत अधिक है। मेरी कक्षा के लिए कोड यहाँ है। हैडर:

// GBWebViewExternalLinkHandler.h 
// TabApp2 
// 
// Created by Luka Mirosevic on 13/03/2013. 
// Copyright (c) 2013 Goonbee. All rights reserved. 
// 

#import <Foundation/Foundation.h> 

@class WebView; 

typedef void(^NewWindowCallback)(NSURL *url); 

@interface GBWebViewExternalLinkHandler : NSObject 

+(WebView *)riggedWebViewWithLoadHandler:(NewWindowCallback)handler; 

@end 

Implemetation:

// GBWebViewExternalLinkHandler.m 
// TabApp2 
// 
// Created by Luka Mirosevic on 13/03/2013. 
// Copyright (c) 2013 Goonbee. All rights reserved. 
// 

#import "GBWebViewExternalLinkHandler.h" 

#import <WebKit/WebKit.h> 

@interface GBWebViewExternalLinkHandler() 

@property (strong, nonatomic) WebView       *attachedWebView; 
@property (strong, nonatomic) GBWebViewExternalLinkHandler  *retainedSelf; 
@property (copy, nonatomic) NewWindowCallback     handler; 

@end 

@implementation GBWebViewExternalLinkHandler 

-(id)init { 
    if (self = [super init]) { 
     //create a new webview with self as the policyDelegate, and keep a ref to it 
     self.attachedWebView = [WebView new]; 
     self.attachedWebView.policyDelegate = self; 
    } 

    return self; 
} 

-(void)webView:(WebView *)sender decidePolicyForNavigationAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request frame:(WebFrame *)frame decisionListener:(id<WebPolicyDecisionListener>)listener { 
    //execute handler 
    if (self.handler) { 
     self.handler(actionInformation[WebActionOriginalURLKey]); 
    } 

    //our job is done so safe to unretain yourself 
    self.retainedSelf = nil; 
} 

+(WebView *)riggedWebViewWithLoadHandler:(NewWindowCallback)handler { 
    //create a new handler 
    GBWebViewExternalLinkHandler *newWindowHandler = [GBWebViewExternalLinkHandler new]; 

    //store the block 
    newWindowHandler.handler = handler; 

    //retain yourself so that we persist until the webView:decidePolicyForNavigationAction:request:frame:decisionListener: method has been called 
    newWindowHandler.retainedSelf = newWindowHandler; 

    //return the attached webview 
    return newWindowHandler.attachedWebView; 
} 

@end 

अपाचे 2.

+0

पुराना लेकिन भयानक, यह बग अभी भी मौजूद प्रतीत होता है और यह जवाब बिल्कुल वही था जो मुझे चाहिए था। –

+0

अभी भी एक अच्छा फिक्स। –

2

के रूप में लाइसेंस के सभी पोस्ट पढ़कर, मैं अपने सरल समाधान के साथ आए हैं, सभी funcs एक ही कक्षा में, यहाँ यह कर रहे हैं ब्राउज़र के साथ एक लिंक खुलता है।

- (WebView *)webView:(WebView *)sender createWebViewWithRequest:(NSURLRequest *)request { 

    return [self externalWebView:sender]; 
} 




- (void)webView:(WebView *)sender decidePolicyForNavigationAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request frame:(WebFrame *)frame decisionListener:(id<WebPolicyDecisionListener>)listener 
{ 
    [[NSWorkspace sharedWorkspace] openURL:[actionInformation objectForKey:WebActionOriginalURLKey]]; 
} 

-(WebView*)externalWebView:(WebView*)newWebView 
{ 
    WebView *webView = newWebView; 

    [webView setUIDelegate:self]; 
    [webView setPolicyDelegate:self]; 
    [webView setResourceLoadDelegate:self]; 
    return webView; 
} 
0

स्पष्टीकरण:

विंडोज createWebViewWithRequest के माध्यम से window.open जाना माध्यम जावास्क्रिप्ट से बनाए गए। सभी विंडो.ओपेन कॉल का परिणाम एक createWebViewWithRequest में होता है: एक शून्य अनुरोध के साथ, बाद में उस वेबव्यू पर एक स्थान बदल जाता है।

अधिक जानकारी के लिए, वेबकिट मेलिंग सूची पर see this old post

0

एक नया WebView लौटने और उसके loadRequest: विधि के लिए इंतज़ार कर के लिए एक वैकल्पिक नाम से जाना, मैं WebView के JSContext में window.open समारोह अधिलेखित समाप्त हो गया:

पहले, मैं WebView की WebFrameLoadDelegate होने के लिए मेरी नियंत्रक सेट :

myWebView.frameLoadDelegate = self; 

फिर, प्रतिनिधि विधि में, मैं window.open समारोह अधिलेखित कर दिया है, और मैं यूआरएल वहाँ के बजाय संसाधित कर सकें।

- (void)webView:(WebView *)webView didCreateJavaScriptContext:(JSContext *)context forFrame:(WebFrame *)frame{ 
context[@"window"][@"open"] = ^(id url){ 
     NSLog(@"url to load: %@", url); 
    }; 
} 

यह मुझे अनुरोध को संभालने देता है हालांकि मुझे अतिरिक्त वेब व्यू बनाने की अजीब आवश्यकता के बिना आवश्यकता होती है।