iOS 자바 스크립트 브리지


101

UIWebView에서 HTML5와 네이티브 iOS 프레임 워크를 함께 사용할 앱을 개발 중입니다. JavaScript와 Objective-C 간의 통신을 구현할 수 있다는 것을 알고 있습니다. 이 통신 구현을 단순화하는 라이브러리가 있습니까? HTML5 및 자바 스크립트 (예 : AppMobi, PhoneGap)로 네이티브 iOS 앱을 만드는 라이브러리가 여러 개 있다는 것을 알고 있지만 자바 스크립트 사용량이 많은 네이티브 iOS 앱을 만드는 데 도움이되는 라이브러리가 있는지 확실하지 않습니다. 다음을 수행해야합니다.

  1. Objective-C에서 JS 메서드 실행
  2. JS에서 Objective-C 메서드 실행
  3. Objective-C에서 네이티브 JS 이벤트 수신 (예 : DOM 준비 이벤트)

1
자바 스크립트 window.webkit.messageHandlers에서 호출 {NAME}이 .postMessage (메시지) 다음과 함께 그것을 처리 : 당신은 WKWebView을 사용할 수 있습니다 [WKUserContentController addScriptMessageHandler : 이름 :] JS에서 오브젝티브 C를 호출 할 수 있습니다.
kostyl

답변:


150

몇 개의 라이브러리가 있지만 큰 프로젝트에서는 사용하지 않았으므로 시도해 보는 것이 좋습니다.

그러나 나는 당신이 직접 시도해 볼 수있을만큼 충분히 간단한 것이라고 생각합니다. 나는 그것을 할 필요가있을 때 개인적으로 정확히 이것을했다. 필요에 맞는 간단한 라이브러리를 만들 수도 있습니다.

1. Objective-C에서 JS 메소드 실행

이것은 실제로 한 줄의 코드입니다.

NSString *returnvalue = [webView stringByEvaluatingJavaScriptFromString:@"your javascript code string here"];

공식 UIWebView 문서 에 대한 자세한 내용 .

2. JS에서 Objective-C 메소드 실행

이것은 불행히도 약간 더 복잡합니다. Mac OSX에 존재하는 동일한 windowScriptObject 속성 (및 클래스)이 둘 사이에 완전한 통신을 허용하기 때문입니다.

그러나 다음과 같은 자바 스크립트 맞춤 URL에서 쉽게 호출 할 수 있습니다.

window.location = yourscheme://callfunction/parameter1/parameter2?parameter3=value

다음과 같이 Objective-C에서 가로 채십시오.

- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {
   NSURL *URL = [request URL]; 
   if ([[URL scheme] isEqualToString:@"yourscheme"]) {
       // parse the rest of the URL object and execute functions
   } 
}

이것은 (또는 windowScriptObject를 사용하여) 깨끗하지는 않지만 작동합니다.

3. Objective-C에서 네이티브 JS 이벤트 수신 (예 : DOM 준비 이벤트)

위의 설명에서이를 수행하려면 JavaScript 코드를 생성하고이를 모니터링하려는 이벤트에 연결 window.location한 다음 가로 채기 위해 올바른 호출을 호출해야합니다.

다시 말하지만, 깨끗하지는 않지만 작동합니다.


12
힌트 : 계획에 밑줄이나 이와 유사한 것을 넣지 마십시오.
fabb

4
당신이 :)로 가정되는 값 반환
Pizzaiola 고르곤 졸라

2
또 다른 힌트 : 깜박임을 방지하기 위해 iFrame에 URL로드
iCaramba 2014

@Folleto 안녕하세요, 당신은 "하지만 나는 큰 프로젝트에서 이것들 중 어느 것도 사용하지 않았다"라고 말했다. 왜 안돼 ?? 이 도서관에서 몇 가지 문제를 발견 했습니까 ??? 미리 감사드립니다.
JERC

1
문제 없습니다. 나는 단순히 그것들을 사용하지 않았기 때문에 더 큰 프로젝트에서 그것들을 사용하는 것에 대해 언급 할 수 없습니다. 나는 그것을 명확히하고 싶었다. :)
Folletto 2015 년

57

수락 된 답변에서 JS에서 목표 c를 호출하는 제안 된 방법은 권장되지 않습니다. 문제의 한 가지 예 : 두 번의 연속 전화를 즉시 걸면 하나는 무시됩니다 (위치를 너무 빨리 변경할 수 없음).

다음 대체 방법을 권장합니다.

function execute(url) 
{
  var iframe = document.createElement("IFRAME");
  iframe.setAttribute("src", url);
  document.documentElement.appendChild(iframe);
  iframe.parentNode.removeChild(iframe);
  iframe = null;
}

execute함수를 반복적으로 호출하고 각 호출이 자체 iframe에서 실행되므로 빠르게 호출 될 때 무시해서는 안됩니다.

이 사람에 대한 크레딧 .


1
또한 너무 빨리 변경되는 .src의 메시지 손실을 방지하기 위해 iOS가 가져올 수있는 JavaScript의 대기열을 사용할 수 있습니다. 위에 링크 된 구현 인 github.com/marcuswestin/WebViewJavascriptBridge 는 대기열 접근 방식을 사용합니다.
kevintcoughlin 2014 년

12

업데이트 : 이것은 iOS 8에서 변경되었습니다. 내 대답은 이전 버전에 적용됩니다.

앱 스토어에서 거부 될 수있는 대안은 WebScriptObject를 사용하는 것입니다.

이러한 API는 OSX에서는 공개되지만 iOS에서는 제공되지 않습니다.

내부 클래스에 대한 인터페이스를 정의해야합니다.

@interface WebScriptObject: NSObject
@end

@interface WebView
- (WebScriptObject *)windowScriptObject;
@end

@interface UIWebDocumentView: UIView
- (WebView *)webView;
@end

WebScriptObject로 사용할 개체를 정의해야합니다.

@interface WebScriptBridge: NSObject
- (void)someEvent: (uint64_t)foo :(NSString *)bar;
- (void)testfoo;
+ (BOOL)isKeyExcludedFromWebScript:(const char *)name;
+ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector;
+ (WebScriptBridge*)getWebScriptBridge;
@end

static WebScriptBridge *gWebScriptBridge = nil;

@implementation WebScriptBridge
- (void)someEvent: (uint64_t)foo :(NSString *)bar
{
    NSLog(bar);
}

-(void)testfoo {
    NSLog(@"testfoo!");
}

+ (BOOL)isKeyExcludedFromWebScript:(const char *)name;
{
    return NO;
}

+ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector;
{
    return NO;
}

+ (NSString *)webScriptNameForSelector:(SEL)sel
{
    // Naming rules can be found at: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/WebKit/Protocols/WebScripting_Protocol/Reference/Reference.html
    if (sel == @selector(testfoo)) return @"testfoo";
    if (sel == @selector(someEvent::)) return @"someEvent";

    return nil;
}
+ (WebScriptBridge*)getWebScriptBridge {
    if (gWebScriptBridge == nil)
        gWebScriptBridge = [WebScriptBridge new];

    return gWebScriptBridge;
}
@end

이제 인스턴스를 UIWebView로 설정하십시오.

if ([uiWebView.subviews count] > 0) {
    UIView *scrollView = uiWebView.subviews[0];

    for (UIView *childView in scrollView.subviews) {
        if ([childView isKindOfClass:[UIWebDocumentView class]]) {
            UIWebDocumentView *documentView = (UIWebDocumentView *)childView;
            WebScriptObject *wso = documentView.webView.windowScriptObject;

            [wso setValue:[WebScriptBridge getWebScriptBridge] forKey:@"yourBridge"];
        }
    }
}

이제 자바 스크립트 내에서 다음을 호출 할 수 있습니다.

yourBridge.someEvent(100, "hello");
yourBridge.testfoo();

내 앱이 앱 스토어에서 거부되었습니다. 내가받은 문제는 "앱에 AppName : UIWebDocumentView의 비공개 클래스가 포함되어 있거나 상 속됨"이었습니다.
chandru

5

iOS8에서는 UIWebView 대신 WKWebView를 볼 수 있습니다 . 이 클래스에는 다음과 같은 클래스가 있습니다. WKScriptMessageHandler : 웹 페이지에서 실행되는 JavaScript에서 메시지를 수신하는 메서드를 제공합니다.


당연히, 상기 방법은 continuoulsy을 실행하지 않고, .. 애플에 의해 제공되는 프레임 워크에 버그가있어
조쉬 Kethepalli

WKWebView쿠키를 제대로 처리하지 않는 등 많은 문제가 있습니다. 당신의 모든 문제를 해결할 것이라고 생각하는 사람을위한 경고 일뿐입니다.
CupawnTae

3

이것은 iOS7에서 가능합니다. http://blog.bignerdranch.com/3784-javascriptcore-and-ios-7/


3
그렇지 않습니다 : JavaScriptCore는 UIWebViews와 상호 작용하지 않습니다. 훌륭한 도구이지만 다른 종류의 문제에 적합합니다. ;)
Folletto 2014 년

1
예, 그렇습니다. JSContext * context = [_webView valueForKeyPath : @ "documentView.webView.mainFrame.javaScriptContext"]; 그러나 JavaScriptCore는 실제로 사용하기에는 너무 버그가 많습니다.
malhal 2014 년

0

가장 좋은 방법은 Appcelerators Titanium 제품입니다. 그들은 이미 웹킷에서 사용하는 V8 엔진 JavascriptCore 엔진을 사용 하여 Obj-C 자바 스크립트 브리지를 구축했습니다 . 또한 오픈 소스이므로 원하는대로 다운로드하고 Obj-C로 수정할 수 있습니다.


@hova, Obj-C V8 브리지가 없습니다. V8은 Android에서만 활용됩니다.
Ross

0

KirinJS 프로젝트 인 Kirin JS 를 살펴보십시오 . 애플리케이션 로직에 Javascript를 사용하고 플랫폼에 적합한 네이티브 UI를 사용할 수 있습니다.


아직 기린에 기여하는 사람이 있습니까? 지난 몇 달 동안 아무 활동도 보지 못했습니다 ...
Sam

0

WebViewJavascriptBridge와 같은 라이브러리를 만들었지 만 JQuery와 비슷하고 설정과 사용이 더 쉽습니다. jQuery에 의존하지 않습니다. 당신이 무슨 생각을하는지 제게 알려주세요! 자키


0

iOS 8에서 WKWebView를 사용하는 경우 자동으로 네이티브 인터페이스를 자바 스크립트에 노출 할 수 있는 XWebView 를 살펴보세요 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.