Pertanyaan Javascript console.log () di iOS UIWebView


Saat menulis aplikasi iPhone / iPad dengan UIWebView, konsol tidak terlihat. jawaban yang sangat bagus ini menunjukkan cara menjebak kesalahan, tetapi saya juga ingin menggunakan console.log ().


74
2018-06-28 14:43


asal


Jawaban:


Setelah berkonsultasi dengan rekan kerja yang terhormat hari ini dia memberi tahu saya tentang Toolkit Pengembang Safari, dan bagaimana ini dapat dihubungkan ke UIWebViews di Simulator iOS untuk keluaran konsol (dan debugging!).

Tangga:

  1. Buka Preferensi Safari -> tab "Lanjutan" -> aktifkan kotak centang "Tampilkan menu Kembangkan di bilah menu"
  2. Mulai aplikasi dengan UIWebView di iOS Simulator
  3. Safari -> Kembangkan -> i (Pad / Pod) Simulator -> [the name of your UIWebView file]

Anda sekarang dapat menjatuhkan kompleks (dalam kasus saya, flot) Javascript dan hal-hal lain ke UIWebViews dan debug sesuka hati.

EDIT: Seperti yang ditunjukkan oleh @Joshua J McKinnon, strategi ini juga berfungsi saat mendebug UIWebViews di perangkat. Cukup aktifkan Web Inspector pada pengaturan perangkat Anda: Pengaturan-> Safari-> Advanced-> Web Inspector (sorak-sorai @Jeremy Wiebe)

UPDATE: WKWebView juga didukung


149
2017-11-27 02:56



Saya memiliki solusi untuk masuk, menggunakan javascript, ke konsol debug aplikasi. Ini agak kasar, tetapi itu berhasil.

Pertama, kita mendefinisikan fungsi console.log () dalam javascript, yang membuka dan segera menghapus iframe dengan ios-log: url.

// 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;

Sekarang kita harus menangkap URL ini di UIWebViewDelegate di aplikasi iOS menggunakan fungsi 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;
}

81
2018-06-28 14:45



Inilah solusi Swift: (Ini sedikit meretas untuk mendapatkan konteks)

  1. Anda membuat UIWebView.

  2. Dapatkan konteks internal dan timpa console.log () fungsi javascript.

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

30
2017-11-17 08:08



Mulai dari iOS7, Anda dapat menggunakan bridge Javascript asli. Sesuatu yang sederhana seperti berikut

 #import <JavaScriptCore/JavaScriptCore.h>

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

24
2018-02-15 19:47



NativeBridge sangat membantu untuk berkomunikasi dari UIWebView ke Objective-C. Anda dapat menggunakannya untuk melewati log konsol dan memanggil fungsi Objective-C.

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

Keuntungan dari teknik ini adalah bahwa hal-hal seperti baris baru dalam pesan log dipertahankan.


8
2018-02-14 20:37



Mencoba memperbaiki Leslie Godwin tetapi mendapatkan kesalahan ini:

'objectForKeyedSubscript' is unavailable: use subscripting

Untuk Swift 2.2, inilah yang berhasil untuk saya:

Anda perlu mengimpor JavaScriptCore untuk dikompilasi kode ini:

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

Kemudian dalam kode javascript Anda, memanggil console.log ("_ your_log_") akan dicetak di konsol Xcode.

Lebih baik lagi, tambahkan kode ini sebagai ekstensi untuk 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")
        }
    }
}

Dan kemudian memanggil metode ini selama langkah inisialisasi UIWebView Anda:

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

0
2017-07-08 21:36