Just My Life & My Work

App和Web雙向溝通:

  • Call Javascript function from Objective-C
  • Call Objective-C function from Javascript

一直是我們想要達成的目標,而先前的兩篇文章:

也就分別實現雙向溝通,只是過程不夠直接,且會衍生一些毛問題。以至於有開源WebViewJavascriptBridge已有6000多顆星,儘管我沒用過XD~

這套件自我介紹:

An iOS/OSX bridge for sending messages between Obj-C and JavaScript in UIWebViews/WebViews

iOS 7以後,SDK發展出JavaScriptCore FrameworkObjective C與Javascript的溝通變得更便利!

先來看一下我範例的畫面,中間白色為UIWebView,讀取專案中某.html檔來顯示,會發現有兩顆按鈕。

iOS Objective C與Javascript的溝通.jpg

HappyTest.html內容:

<body>
    <input type='button' onclick="javascript:happy()" value="Happy">
        <input type='button' onclick="javascript:world()" value="World">
            <script>
                function happy() {
                    print("Hello, Happy World!");
                }
            
                function world() {
                
                }
            
            </script>
</body>

溝通測試實做:

/**
 Theme: Objective C and WebView Communication
 IDE: Xcode 7
 Language: Objective C
 Date: 105/06/02
 Author: HappyMan
 Blog: https://cg2010studio.wordpress.com/
 */
-(void)setupWebView
{
    // set up a full-screen UIWebView
    UIView *view = self.view;
    UIWebView *webView = [[UIWebView alloc] init];
    webView.delegate = self;
    [view addSubview:webView];
    webView.translatesAutoresizingMaskIntoConstraints = view.translatesAutoresizingMaskIntoConstraints = NO;
    for (NSString *fitFormat in @[@"H:|-50-[webView]-50-|", @"V:|-50-[webView]-50-|"])
        [view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:fitFormat options:0 metrics:nil views:NSDictionaryOfVariableBindings(webView)]];

    NSString *htmlPath = [[NSBundle mainBundle] pathForResource:@"HappyTest" ofType:@"html"];
    NSString *htmlString = [NSString stringWithContentsOfFile:htmlPath encoding:NSUTF8StringEncoding error:nil];
    [webView loadHTMLString:htmlString baseURL:nil];
}

#pragma mark - UIWebViewDelegate
-(void)webViewDidFinishLoad:(UIWebView *)webView
{
    NSLog(@"webViewDidFinishLoad");

    JSContext *ctx = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    NSAssert([ctx isKindOfClass:[JSContext class]], @"could not find context in web view");

//    ctx[@"happy"] = ^() {
//        NSLog(@"happy");
//    };
    ctx[@"print"] = ^(NSString *text) {
        NSLog(@"%@", text);
    };

    JSValue *happyFunction = ctx[@"happy"];
    [happyFunction callWithArguments:nil];

    ctx[@"world"] = ^() {
        NSLog(@"world");

        UIAlertView *av = [[UIAlertView alloc] initWithTitle:@"Happy Test" message:@"Be Happy ^_^" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
        [av show];
    };

    JSValue *worldFunction = ctx[@"world"];
    [worldFunction callWithArguments:nil];
}

當網頁載入完畢後,會出現Log:

webViewDidFinishLoad
Hello, Happy World!
world

可以看到後兩行來自block執行的結果,而第二行的字眼來自HappyTest.html中的Javascript。這部分屬於:

  • Call Javascript function from Objective-C

接著我們在UIWebView上分別按兩顆按鈕,會分別觸發兩個block。這部分則代表:

  • Call Objective-C function from Javascript

是不是相當直覺呢?

可以發現Objective C與Javascript各有三個關鍵字:

  • happy
  • print
  • world

兩邊共同遵守規則,就能互通有無囉~

取得Context目前要找這個路徑:

documentView.webView.mainFrame.javaScriptContext

尚不知有無例外,可能要多瞭解一下網頁程式設計。

以上是基本的範例,還有更高深的用法,再去請益高人指點吧!

參考:

Comments on: "[iOS] Objective C與Javascript的溝通" (3)

  1. 現在寫加密 WebView,要取得 App 登入 Token,需要用到~

  2. […] iOS 7之後有更好的做法,可參考文章:Objective C與Javascript的溝通。 […]

  3. […] iOS 7之後有更好的做法,可參考文章:Objective C與Javascript的溝通。 […]

隨意留個言吧:)~

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com 標誌

您的留言將使用 WordPress.com 帳號。 登出 /  變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 /  變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 /  變更 )

連結到 %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

標籤雲

%d 位部落客按了讚: