IOS UIWebView में जावास्क्रिप्ट कंसोल कंसोल ()


84

UIWebView के साथ iPhone / iPad ऐप लिखते समय, कंसोल दिखाई नहीं देता है। यह उत्कृष्ट उत्तर यह दिखाता है कि त्रुटियों को कैसे फँसाया जाए, लेकिन मैं साथ ही कंसोल.लॉग () का उपयोग करना चाहूंगा।


1
इसे पहले ब्राउज़र में लिखें, डेवलपर टूल चालू करें, फिर कंसोल आउटपुट देखें।
बीटगैमिट

जवाबों:


183

एक सम्मानित सहयोगी के साथ परामर्श करने के बाद आज उन्होंने मुझे सफारी डेवलपर टूलकिट के लिए सतर्क किया, और यह कंसोल आउटपुट (और डिबगिंग!) के लिए iOS सिम्युलेटर में UIWebViews से कैसे जुड़ा जा सकता है।

कदम:

  1. सफारी प्राथमिकताएं खोलें -> "उन्नत" टैब -> चेकबॉक्स सक्षम करें "मेनू बार में मेनू दिखाएं"
  2. IOS सिम्युलेटर में UIWebView के साथ ऐप शुरू करें
  3. सफारी -> विकसित -> i (पैड / पॉड) सिम्युलेटर -> [the name of your UIWebView file]

अब आप जटिल (मेरे मामले में, फ़्लोट ) जावास्क्रिप्ट और अन्य सामान को UIWebViews में छोड़ सकते हैं और अपनी इच्छानुसार डिबग कर सकते हैं।

EDIT: जैसा कि @Joshua J McKinnon ने बताया कि यह रणनीति तब भी काम करती है जब किसी डिवाइस पर UIWebViews को डीबग करता है। बस अपने डिवाइस सेटिंग्स पर वेब इंस्पेक्टर को सक्षम करें: सेटिंग्स-> सफारी-> उन्नत-> वेब इंस्पेक्टर (चीयर्स @ जेरेमी होई)

अद्यतन: WKWebView भी समर्थित है


13
ध्यान दें, यह रणनीति वास्तविक आईओएस उपकरणों पर डिबगिंग के दौरान भी काम करती है।
जोशुआ जे। मैकिनॉन 3

2
+100 अगर मैं कर सका। यह अद्भुत है, यह फोन गैप ऐप्स के लिए भी काम करता है!
एंडी नोवोसिन

2
आईपैड के साथ कोशिश करते हुए, जब मैं सफारी पर विकसित मेनू पर जाता हूं, तो चुनने के लिए कोई उपकरण नहीं हैं। जब मैं सिम्युलेटर पर तैनात होता हूं, तो यह एक आकर्षण की तरह काम करता है।
फ्लोयडियन

10
@ फ़्लोयडियन आपको डिवाइस पर वेब इंस्पेक्टर को सक्षम करना होगा। सेटिंग्स-> सफारी-> उन्नत-> वेब इंस्पेक्टर।
जेरेमी विएबे

2
मेरा ऐप मेरे विकसित मेनू में दिखाई नहीं दे रहा है। मैंने वेब इंस्पेक्टर को सक्षम किया है। सफारी दिखाता है, लेकिन मेरा ऐप (जो वर्तमान है? 2 UIWebviews को प्रदर्शित करता है) का पता नहीं लगाया गया है .. कोई विचार?
नार्को

82

मेरे पास ऐप्स डिबग कंसोल के लिए जावास्क्रिप्ट का उपयोग करके लॉग इन करने का समाधान है। यह थोड़ा कच्चा है, लेकिन यह काम करता है।

सबसे पहले, हम जावास्क्रिप्ट में कंसोल.लॉग () फ़ंक्शन को परिभाषित करते हैं, जो खोलता है और तुरंत एक आईओएस-लॉग: यूआरएल के साथ एक आइफ्रेम निकालता है।

// Debug
console = new Object();
console.log = function(log) {
  var iframe = document.createElement("IFRAME");
  iframe.setAttribute("src", "ios-log:#iOS#" + log);
  document.documentElement.appendChild(iframe);
  iframe.parentNode.removeChild(iframe);
  iframe = null;    
};
console.debug = console.log;
console.info = console.log;
console.warn = console.log;
console.error = console.log;

अब हमें इस यूआरएल को UIWebViewDelegate में iOS ऐप में shouldStartLoadWithRequest फ़ंक्शन का उपयोग करके पकड़ना है।

- (BOOL)webView:(UIWebView *)webView2 
shouldStartLoadWithRequest:(NSURLRequest *)request 
 navigationType:(UIWebViewNavigationType)navigationType {

    NSString *requestString = [[[request URL] absoluteString] stringByReplacingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
    //NSLog(requestString);

    if ([requestString hasPrefix:@"ios-log:"]) {
        NSString* logString = [[requestString componentsSeparatedByString:@":#iOS#"] objectAtIndex:1];
                               NSLog(@"UIWebView console: %@", logString);
        return NO;
    }

    return YES;
}

1
नीचे NSTJ का सरल विचार देखें।
अश्विन एस


35

यहाँ स्विफ्ट समाधान है: (यह संदर्भ प्राप्त करने के लिए एक हैक का एक सा है)

  1. आप UIWebView बनाएं।

  2. आंतरिक संदर्भ प्राप्त करें और कंसोल.लॉग () जावास्क्रिप्ट फ़ंक्शन को ओवरराइड करें ।

    self.webView = UIWebView()
    self.webView.delegate = self
    
    let context = self.webView.valueForKeyPath("documentView.webView.mainFrame.javaScriptContext") as! JSContext
    
    let logFunction : @convention(block) (String) -> Void =
    {
        (msg: String) in
    
        NSLog("Console: %@", msg)
    }
    context.objectForKeyedSubscript("console").setObject(unsafeBitCast(logFunction, AnyObject.self), 
                                                         forKeyedSubscript: "log")
    

3
+100! मुझे बचाया, समय की TONS, महान हैक, जेएस कोड में 0 परिवर्तन की आवश्यकता है। धन्यवाद!! भविष्य के पाठकों के लिए बस मेरे 2 सेंट: JavaScriptCoreअपने प्रोजेक्ट को फ्रेमवर्क लिंक करना न भूलें और importयह आपके वेबव्यू स्विफ्ट फाइल में है।
माइंडबॉम्ब

। स्विफ्ट 4 के साथ मेरे लिए काम करता है ... आप NSString..context.objectForKeyedSubscript ( "कंसोल") setObject करने के लिए "लॉग" डाली haveto (: AnyObject.self), forKeyedSubscript: unsafeBitCast (logFunction, करने के लिए NSString के रूप में "लॉग")
सर्ज

28

IOS7 से शुरू होकर, आप देशी जावास्क्रिप्ट ब्रिज का उपयोग कर सकते हैं। निम्नलिखित के रूप में कुछ सरल है

 #import <JavaScriptCore/JavaScriptCore.h>

JSContext *ctx = [webview valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
ctx[@"console"][@"log"] = ^(JSValue * msg) {
NSLog(@"JavaScript %@ log message: %@", [JSContext currentContext], msg);
    };

ब्याज से बाहर, इस कोड को रखने के लिए आदर्श स्थान कहां है?
लेस्ली गॉडविन

ठीक है, यह पता लगा। आपके द्वारा बनाए जाने के बाद आप UIWebviewकिसी भी JSContextसामान को सेटअप कर सकते हैं ।
लेस्ली गॉडविन

4
JSContextअभी भी iOS 8+ में काम करता है WKWebView?
निकोलाई सैमटेलडज 18

मैंने इसे डाल दिया - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationTypeऔर यह पूरी तरह से काम करता है!
अर्तूर बार्टिसक

@NikolaiSamteladze: मैंने WKWebViewऔर iOS 11.4.1 के साथ प्रयास किया और वह नहीं मिल सका documentViewऔर क्रैश हो गया। मैंने इसका उत्तर देखा और ऐसा लगता है कि, यह इस तरह संभव नहीं है।
परीक्षण

10

NativeBridge एक UIWebView से ऑब्जेक्टिव-सी तक संचार करने के लिए बहुत सहायक है। आप इसका उपयोग कंसोल लॉग को पास करने और ऑब्जेक्टिव-सी फ़ंक्शन को कॉल करने के लिए कर सकते हैं।

https://github.com/ochameau/NativeBridge

console = new Object();
console.log = function(log) {
    NativeBridge.call("logToConsole", [log]);
};
console.debug = console.log;
console.info = console.log;
console.warn = console.log;
console.error = console.log;

window.onerror = function(error, url, line) {
    console.log('ERROR: '+error+' URL:'+url+' L:'+line);
};

इस तकनीक का फायदा यह है कि लॉग मैसेज में नईलाइन जैसी चीजें संरक्षित रहती हैं।


+1। अपाचे कॉर्डोवा उपयोगकर्ताओं पर ध्यान दें - कॉर्डोवा पहले से ही संभालती है console.log, लेकिन window.onerrorइस जवाब में फ़ंक्शन बहुत उपयोगी है!
एमपॉन्टिल्लो

Appcelerator / Titanium Developers के लिए: यह भी आपके Ti.UI.WebView को डीबग करने का काम करता है
Byters

0

लेस्ली गॉडविन को ठीक करने की कोशिश की लेकिन यह त्रुटि हो रही थी:

'objectForKeyedSubscript' is unavailable: use subscripting

स्विफ्ट 2.2 के लिए, यहाँ मेरे लिए क्या काम किया गया है:

इस कोड को संकलित करने के लिए आपको JavaScriptCore को आयात करना होगा:

import JavaScriptCore

if let context = webView.valueForKeyPath("documentView.webView.mainFrame.javaScriptContext") {
    context.evaluateScript("var console = { log: function(message) { _consoleLog(message) } }")
    let consoleLog: @convention(block) String -> Void = { message in
        print("javascript_log: " + message)
    }
    context.setObject(unsafeBitCast(consoleLog, AnyObject.self), forKeyedSubscript: "_consoleLog")
}

फिर आपके जावास्क्रिप्ट कोड में, कॉलिंग कंसोल .log ("_ your_log_") Xcode कंसोल में प्रिंट होगा।

बेहतर अभी तक, इस कोड को UIWebView के विस्तार के रूप में जोड़ें:

import JavaScriptCore

extension UIWebView {
    public func hijackConsoleLog() {
        if let context = valueForKeyPath("documentView.webView.mainFrame.javaScriptContext") {
            context.evaluateScript("var console = { log: function(message) { _consoleLog(message) } }")
            let consoleLog: @convention(block) String -> Void = { message in
                print("javascript_log: " + message)
            }
            context.setObject(unsafeBitCast(consoleLog, AnyObject.self), forKeyedSubscript: "_consoleLog")
        }
    }
}

और फिर अपने UIWebView आरंभीकरण चरण के दौरान इस विधि को कॉल करें:

let webView = UIWebView(frame: CGRectZero)
webView.hijackConsoleLog()

0

स्विफ्ट 5

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
      webView.evaluateJavaScript("your javascript string") { (value, error) in
          if let errorMessage = (error! as NSError).userInfo["WKJavaScriptExceptionMessage"] as? String {
                print(errorMessage)
          }
      }
 }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.