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 Framework,Objective C與Javascript的溝通變得更便利!
先來看一下我範例的畫面,中間白色為UIWebView,讀取專案中某.html檔來顯示,會發現有兩顆按鈕。
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
- world
兩邊共同遵守規則,就能互通有無囉~
取得Context目前要找這個路徑:
documentView.webView.mainFrame.javaScriptContext
尚不知有無例外,可能要多瞭解一下網頁程式設計。
以上是基本的範例,還有更高深的用法,再去請益高人指點吧!
參考:
Comments on: "[iOS] Objective C與Javascript的溝通" (3)
現在寫加密 WebView,要取得 App 登入 Token,需要用到~
讚讚
[…] iOS 7之後有更好的做法,可參考文章:Objective C與Javascript的溝通。 […]
讚讚
[…] iOS 7之後有更好的做法,可參考文章:Objective C與Javascript的溝通。 […]
讚讚