IOS開發(fā)中Objective-C與JS互相調(diào)用實(shí)例教程
本文我們來講講iOS系統(tǒng)上通用的本地Objective-C代碼與Javascript互操作的基本方法悦陋,本文還涉及到html5的應(yīng)用,這里把實(shí)現(xiàn)方法簡單介紹棋返。
項(xiàng)目中要用到html5來實(shí)現(xiàn)味廊,涉及到Objective-C調(diào)用JS蒸甜,以及JS調(diào)用Objective-C的方法,這里把遇到的問題以及實(shí)現(xiàn)方法介紹一下毡们。
Objective-C
//
// ViewController.h
// OC_And_JS
//
// Created by 張杰 on 15/7/9.
// Copyright ? 2015年 張杰. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController <UIWebViewDelegate>
@property (weak, nonatomic) IBOutlet UIButton *oc_call_js_no_params;
@property (weak, nonatomic) IBOutlet UIButton *oc_call_js_has_params;
@property (weak, nonatomic) IBOutlet UIWebView *mWebView;
@property (weak, nonatomic) IBOutlet UILabel *js_call_oc_show;
- (IBAction)ocCallJsNoParams:(id)sender;
- (IBAction)ocCallJsHasParams:(id)sender;
@end
Objective-C
//
// ViewController.m
// OC_And_JS
//
// Created by 張杰 on 15/7/9.
// Copyright ? 2015年 張杰. All rights reserved.
//
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
_mWebView.delegate = self;
//打開URL
NSString *path = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html"];
[self.mWebView loadRequest:[NSURLRequest <a href="/tags.php/request/" target="_blank">request</a>WithURL:[NSURL fileURLWithPath: path]]];
}
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
NSString *urlstr = request.URL.absoluteString;
NSRange range = [urlstr rangeOfString:@"ios://jwzhangjie"];
if (range.length!=0) {
_js_call_oc_show.text = [NSString stringWithFormat:@"請?jiān)L問地址:%@", urlstr];
}
return YES;
}
-(void)webView:(nonnull UIWebView *)webView didFailLoadWithError:(nullable NSError *)error{
NSLog(@"加載失敗");
}
-(void)webViewDidStartLoad:(nonnull UIWebView *)webView{
NSLog(@"開始加載");
}
-(void)webViewDidFinishLoad:(nonnull UIWebView *)webView{
NSLog(@"開始結(jié)束");
// 對于調(diào)用js的時(shí)候最好這個(gè)方法里面或者之后
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)ocCallJsNoParams:(id)sender {
NSString *js = [NSString stringWithFormat:@"ocCallJsNoParamsFunction();"];
[self.mWebView stringByEvaluatingJavaScriptFromString:js];
}
- (IBAction)ocCallJsHasParams:(id)sender {
NSString *js = [NSString stringWithFormat:@"ocCallJsHasParamsFunction('%@','%@');",@"jwzhangjie",@"http://jwzhangjie.cn"];
[self.mWebView stringByEvaluatingJavaScriptFromString:js];
}
@end
JavasSctipt
function ocCallJsNoParamsFunction()
{
alert("OC調(diào)用JS中的無參方法");
var e = document.getElementById("js_shouw_text");
e.options.add(new Option("OC調(diào)用JS中的無參方法", 2));
}
function ocCallJsHasParamsFunction(name, url)
{
alert(name+"的博客地址為:"+url);
var e = document.getElementById("js_shouw_text");
e.options.add(new Option("OC調(diào)用JS中的有參方法", 2));
}
html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>OC與JS互相調(diào)用</title>
</head>
<body>
<div >
<<a href="/tags.php/select/" target="_blank">select</a> id="js_shouw_text">
<option>
展示OC調(diào)用JS無參數(shù)
</option>
</select>
</div>
<div>
<BR/>
<input type="button" value="JS調(diào)用OC方法" onclick="js_call_oc()"/>
</div>
<!-- 這里要清楚迅皇,雖然test.js跟index.html不同及目錄,實(shí)際安裝到程序里面后衙熔,是在同級目錄的登颓,所以這里src不能加目錄,同樣css也是一樣的 -->
<script type="text/<a href="/js_a/js.html" target="_blank">javascript</a>" src="test.js" charset="UTF-8"></script>
<script type="text/javascript">
function js_call_oc()
{
var iFrame;
iFrame = document.createElement("<a href="/tags.php/iframe/" target="_blank">iframe</a>");
iFrame.setAttribute("src", "ios://jwzhangjie");
iFrame.setAttribute("style", "display:none;");
iFrame.setAttribute("height", "0px");
iFrame.setAttribute("width", "0px");
iFrame.setAttribute("frameborder", "0");
document.body.appendChild(iFrame);
// 發(fā)起請求后這個(gè)iFrame就沒用了红氯,所以把它從dom上移除掉
iFrame.parentNode.removeChild(iFrame);
iFrame = null;
}
</script>
</body>
</html>
規(guī)避1:對于OC去調(diào)用JS內(nèi)容最好在webViewDidFinishLoad方法里或者之后
規(guī)避2:在html里面引用js或者css的時(shí)候src不要帶有路徑框咙,因?yàn)榘惭b后文件都在同級目錄下面
規(guī)避3:OC調(diào)用JS的規(guī)范
NSString *js = [NSString stringWithFormat:@"ocCallJsHasParamsFunction('%@','%@');",@"jwzhangjie",@"http://jwzhangjie.cn"];
[self.mWebView stringByEvaluatingJavaScriptFromString:js];
規(guī)避4:JS調(diào)用OC,這里通過html里面發(fā)送一個(gè)請求痢甘,然后在ios中使用shouldStartLoadWithRequest攔截請求喇嘱,根據(jù)請求url的不同進(jìn)行處理。
javascript
function js_call_oc()
{
var iFrame;
iFrame = document.createElement("iframe");
iFrame.setAttribute("src", "ios://jwzhangjie");
iFrame.setAttribute("style", "display:none;");
iFrame.setAttribute("height", "0px");
iFrame.setAttribute("width", "0px");
iFrame.setAttribute("frameborder", "0");
document.body.appendChild(iFrame);
// 發(fā)起請求后這個(gè)iFrame就沒用了塞栅,所以把它從dom上移除掉
iFrame.parentNode.removeChild(iFrame);
iFrame = null;
}
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
NSString *urlstr = request.URL.absoluteString;
NSRange range = [urlstr rangeOfString:@"ios://jwzhangjie"];
if (range.length!=0) {
_js_call_oc_show.text = [NSString stringWithFormat:@"請?jiān)L問地址:%@", urlstr];
}
return YES;
}
javascript與Objective-C的相互調(diào)用
Objective-C調(diào)用Javascript方法:
前提:
UIWebView已經(jīng)完全加載完成包含需要調(diào)用的頁面(注:在UIWebViewDelegate托管中通過監(jiān)視- (void)webViewDidFinishLoad:(UIWebView *)webView調(diào)用來確定頁面是否加載完成)者铜。
方法:
假設(shè)某視圖對象的子視圖屬性self.webview加載的頁面包含如下Javascript函數(shù):
function getString(){ return “Hello javascript!”;}
并且該函數(shù)在該頁面上可被正常調(diào)用,則可以通過形如下面的Objectvie-C方法調(diào)用此函數(shù):
NSString *str = [self.webview stringByEvaluatingJavaScriptFromString:@"getString();"];
該函數(shù)調(diào)用實(shí)際模擬了頁面上的一次Javascript函數(shù)調(diào)用,因此在該函數(shù)內(nèi)部任何有效的Javascript代碼都可被執(zhí)行作烟!該Objective-C代碼返回值為被調(diào)用的Javascript代碼的返回值愉粤,在上例中,str的值將被賦為@”Hello javascript!”拿撩。
被調(diào)用的函數(shù)可以帶有字符串或數(shù)值型的參數(shù)衣厘。若調(diào)用的Javascript函數(shù)名稱帶有參數(shù),需保證傳進(jìn)去的參數(shù)的格式正確性压恒,特別是字符串參數(shù)的引號很容易被忽略影暴。
系統(tǒng)響應(yīng)頁面Javascript代碼:
前提:
需要實(shí)現(xiàn)UIWebViewDelegate的
- (BOOL)webView:(UIWebView *)webView
shouldStartLoadWithRequest:(NSURLRequest *)request
navigationType:(UIWebViewNavigationType)navigationType;
托管函數(shù)(以下簡稱跳轉(zhuǎn)監(jiān)視函數(shù))并將實(shí)現(xiàn)了該托管函數(shù)的對象設(shè)置為UIWebView的delegate。
方法:
UIWebView的當(dāng)前頁面將要被Javascript代碼通過以下方式轉(zhuǎn)向的時(shí)候探赫,會調(diào)用上述跳轉(zhuǎn)監(jiān)視函數(shù):
window.location.href=”http://www.strongsoft.net”;
此時(shí)實(shí)現(xiàn)了該托管協(xié)議的對象的跳轉(zhuǎn)監(jiān)視函數(shù)會被調(diào)用型宙,通過如下代碼監(jiān)視瀏覽器跳轉(zhuǎn)的地址:
NSString *url = [[request URL] absoluteString];
若該托管函數(shù)返回值為NO,則頁面UIWebView的頁面跳轉(zhuǎn)將被否決期吓。利用這一思路早歇,監(jiān)視頁面上的特定格式的跳轉(zhuǎn)地址加以攔截,并執(zhí)行相應(yīng)的本地代碼讨勤,即可實(shí)現(xiàn)Javascript與Objective-C代碼的交互箭跳。
例如,規(guī)定攔截URL地址前綴為”objc:”的所有地址潭千,并且用if…else…語句判定本地需要執(zhí)行的代碼谱姓,則實(shí)現(xiàn)形如以下格式的Objective-C托管函數(shù):
- (BOOL)webView:(UIWebView *)webView
shouldStartLoadWithRequest:(NSURLRequest *)request
navigationType:(UIWebViewNavigationType)navigationType
{
NSString *urlString = [[request URL] absoluteString];
NSArray *urlComps = [urlString componentsSeparatedByString:@":"];
if([urlComps count] && [[urlComps objectAtIndex:o] isEqualToString:@"objc"])
{
NSString *funcStr = [urlComps objectAtIndex:1];
if([funcStr isEqualToString:@"doFunc1"])
{
}
else if([funcStr isEqualToString:@"doFunc2"])
{
}
return NO;
}
return YES;
}
當(dāng)需要調(diào)用本地函數(shù)1時(shí),可以通過如下Javascript函數(shù)進(jìn)行:
window.location.href=”objc:doFunc1”;
根據(jù)上述思路刨晴,可以完善通過Javascript調(diào)用本地帶參數(shù)的Objective-C代碼屉来。