iOS UIWebView의 Javascript console.log ()


84

UIWebView로 iPhone / iPad 앱을 작성할 때 콘솔이 표시되지 않습니다. 이 훌륭한 대답 은 오류를 잡는 방법을 보여 주지만 console.log ()도 사용하고 싶습니다.


1
먼저 브라우저에 작성하고 개발자 도구를 켠 다음 콘솔 출력을 확인하십시오.
beatgammit 2011 년

답변:


183

오늘 존경하는 동료와상의 한 후 그는 Safari 개발자 툴킷에 대해 알려 주었으며, 콘솔 출력 (및 디버깅!)을 위해 iOS 시뮬레이터의 UIWebView에 어떻게 연결할 수 있는지 알려주었습니다.

단계 :

  1. Safari 환경 설정 열기-> "고급"탭-> "메뉴 막대에 개발 메뉴 표시"확인란을 활성화합니다.
  2. iOS 시뮬레이터에서 UIWebView로 앱 시작
  3. Safari-> 개발-> i (Pad / Pod) 시뮬레이터-> [the name of your UIWebView file]

이제 복잡한 (제 경우에는 flot ) Javascript 및 기타 항목을 UIWebViews에 드롭 하고 원하는대로 디버그 할 수 있습니다.

편집 : @Joshua J McKinnon이 지적했듯이이 전략은 장치에서 UIWebViews를 디버깅 할 때도 작동합니다. 장치 설정에서 Web Inspector를 활성화하기 만하면됩니다 : Settings-> Safari-> Advanced-> Web Inspector (@Jeremy Wiebe 건배)

업데이트 : WKWebView도 지원됩니다.


13
이 전략은 실제 iOS 장치에서 디버깅 할 때도 작동합니다.
Joshua J. McKinnon 2013

2
내가 할 수 있다면 +100. 이것은 훌륭합니다. 전화 간격 앱에서도 작동합니다!
Andy Novocin 2014

2
iPad를 사용해 보면 Safari의 개발 메뉴로 이동하면 선택할 장치가 없습니다. 시뮬레이터에 배치하면 매력처럼 작동합니다.
Floydian 2014 년

10
@Floydian은 장치에서 Web Inspector를 활성화해야합니다. 설정-> Safari-> 고급-> Web Inspector.
Jeremy Wiebe

2
내 앱이 개발 메뉴에 표시되지 않습니다. 웹 검사기를 활성화했습니다. Safari가 나타나지만 내 앱 (현재 UIWebview 2 개 표시)이 감지되지 않습니다. 아이디어가 있습니까?
narco

83

자바 스크립트를 사용하여 앱 디버그 콘솔에 로깅하는 솔루션이 있습니다. 약간 조잡하지만 작동합니다.

먼저 ios-log : url로 iframe을 열고 즉시 제거하는 javascript에서 console.log () 함수를 정의합니다.

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

이제 shouldStartLoadWithRequest 함수를 사용하여 iOS 앱의 UIWebViewDelegate에서이 URL을 포착해야합니다.

- (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의 간단한 아이디어를 참조하십시오.
Ashwin S

스위프트 4에서 아마도? : D
Konstantinos Natsios

35

다음은 Swift 솔루션입니다. (컨텍스트를 얻는 것은 약간의 해킹입니다)

  1. UIWebView를 만듭니다.

  2. 내부 컨텍스트를 가져오고 console.log () 자바 스크립트 함수를 재정의합니다 .

    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! 시간 절약, 훌륭한 해킹, JS 코드 변경이 필요하지 않습니다. 감사!! 미래 독자를위한 2 센트 만 : JavaScriptCore프레임 워크를 프로젝트와 import웹뷰 신속한 파일 에 연결하는 것을 잊지 마십시오 .
mindbomb

. 스위프트 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);
    };

흥미롭게도이 코드를 넣을 수있는 이상적인 장소는 어디입니까?
Leslie Godwin

좋아, 알아 냈어. 를 만든 직후에 UIWebview모든 항목을 설정할 수 있습니다 JSContext.
Leslie Godwin

4
JSContextiOS 8 이상에서 계속 작동 합니까 WKWebView?
Nikolai Samteladze

나는 그것을 넣고 - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType완벽하게 작동합니다!
Artur Bartczak

@NikolaiSamteladze : WKWebViewiOS 11.4.1을 사용해 보았지만 찾을 수없고 documentView충돌이 발생했습니다. 나는이 대답을 보았고 이런 식으로 불가능한 것 같습니다.
테스트

10

NativeBridge는 UIWebView에서 Objective-C로 통신하는 데 매우 유용합니다. 이를 사용하여 콘솔 로그를 전달하고 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);
};

이 기술의 장점은 로그 메시지의 줄 바꿈과 같은 항목이 보존된다는 것입니다.


+1. Apache Cordova 사용자에 대한 참고 사항 -Cordova는 이미을 처리 console.log하지만 window.onerror이 답변 의 기능은 매우 유용합니다!
mpontillo 2013

Appcelerator / 티타늄 개발자 :이 너무 귀하의 Ti.UI.WebView 디버깅하기 위해 노력
Byters

0

Leslie Godwin의 수정을 시도했지만 다음 오류가 발생했습니다.

'objectForKeyedSubscript' is unavailable: use subscripting

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

그런 다음 자바 스크립트 코드에서 console.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)
          }
      }
 }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.