programing

iOS 자바 스크립트 브리지

nasanasas 2020. 8. 20. 18:56
반응형

iOS 자바 스크립트 브리지


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. 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한 다음 가로 채기 위해 올바른 호출을 호출해야합니다.

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


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

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

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

You call the execute function repeatedly and since each call executes in its own iframe, they should not be ignored when called quickly.

Credits to this guy.


Update: This has changed in iOS 8. My answer applies to previous versions.

An alternative, that may get you rejected from the app store, is to use WebScriptObject.

These APIs are public on OSX but are not on iOS.

You need to define interfaces to the internal classes.

@interface WebScriptObject: NSObject
@end

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

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

You need to define your object that's going to serve as your 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

Now set that an instance to your 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"];
        }
    }
}

Now inside of your javascript you can call:

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

In iOS8 you can look at WKWebView instead of UIWebView. This has the following class: WKScriptMessageHandler: Provides a method for receiving messages from JavaScript running in a webpage.


This is possible with iOS7, checkout http://blog.bignerdranch.com/3784-javascriptcore-and-ios-7/


Your best bet is Appcelerators Titanium offering. They already have built a Obj-C javascript bridge using the V8 engine JavascriptCore engine used by webkit. It's also open source, so you'll be able to download it and tinker with the Obj-C as you like.


Have a look at the KirinJS project: Kirin JS which allows to use Javascript for the application logic and native UI adequate to the platform it runs on.


I created a library like WebViewJavascriptBridge, but it's more JQuery-like, has easier to setup and is easier to use. Doesn't rely on jQuery (though to its credit, had I known WebViewJavascriptBridge existed before writing this I may just have held back slightly before diving in). Let me know what you think! jockeyjs


If you are using WKWebView on iOS 8, take a look the XWebView which can automatically expose the native interface to javascript.

참고URL : https://stackoverflow.com/questions/9473582/ios-javascript-bridge

반응형