256
人物
H5和NA(WebView)的交互
H5和NA(WebView)的交互
URL攔截
NA->H5數據傳遞
使用stringByEvaluatingJavaScriptFromString,直接調用H5的函數名字,參數的json字符串:
例如:
- (void)webViewDidFinishLoad:(UIWebView *)webView {
NSMutableDictionary *dictInfo = [NSMutableDictionary dictionary];
[dictInfo setValue:@"value1" forKey:@"key1"];
[dictInfo setValue:@"value2" forKey:@"key2"];
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dictInfo options:kNilOptions error:nil];
if (jsonData) {
NSString *strValueJson = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
NSString *jsCode = [NSString stringWithFormat:@"picCallback&& picCallback(%@)", strValueJson];
[webView stringByEvaluatingJavaScriptFromString:jsCode];
}
}
H5->NA數據傳遞
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<div >
<h1>Objective-C和JavaScript交互的那些事</h1>
<input type="button" value="CallCameraByUrl" >
</div>
<script>
function callCameraByUrl(){
window.location.href = 'toyun://callCamera';
}
</script>
</body>
</html>
window.location.href這裏是改變主窗口的指向從而馬上發出一個鏈接為Toyun://callCamera請求,而想要傳給原生應用的參數也可已包含到此請求中,而在iOS方法中我們要攔截這個請求,根據請求內容去判斷JavaStript想要做的事情,從而實現web頁麵和本地應用之間的交互
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
NSString *url = request.URL.absoluteString;
if ([url rangeOfString:@"toyun://"].location != NSNotFound) {
// url的協議頭是Toyun
NSLog(@"callCamera");
return NO;
}
return YES;
}
注意:url後麵可以拚接參數,參數的每個value要在H5裏麵單獨轉碼,避免特殊符號,&=以及中文.....
轉碼
H5的url上麵每個value要單獨進行encodeURIComponent的轉碼,之後再拚接成toyun://callCamera?key1=value1,比如:encodeURIComponent(value1)。
JS傳遞
H5代碼:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<div >
<h1>Objective-C和JavaScript交互的那些事</h1>
<input type="button" value="CallCamera" >
</div>
<div >
<input type="button" value="share" >
</div>
<script type="text/javascript">
function callShare()
{
var shareInfo = JSON.stringify({"title":"標題","desc":"內容","shareUrl":"https://www.jianshu.com/p/f896d73c670a"});
Toyun.share(shareInfo);
}
</script>
<script>
function picCallback(photos){
alert(photos);
}
</script>
<script>
function shareCallback(){
alert("success");
}
</script>
</body>
</html>
對H5稍作解釋:
先說Toyun是iOS和Android這兩邊在本地要注入的一個對象【參考下麵iOS的代碼更容易明白】,充當原生應用和web頁麵之間的一個橋梁。頁麵上定義了兩個按鈕名字分別為CallCamera和Share。
點擊CallCamera會調用Toyun最終橋梁對象的方法:callCamera()。而點擊Share會先調用本文件中的javascript方法callShared(),這裏將要分享的內容格式轉為Json字符串格式,然後再調用Toyun最終橋梁對象的方法: (void)share:(NSString *)shareInfo方法這個是有傳參的,參數為shareInfo。
而下麵的兩個方法為原生方法調用後的回調方法,其中picCallback為獲取圖片成功的回調方法,並且傳回拿到的圖片photos;shareCallback為分享成功的回調方法。
IOS:
JSContext:給JavaScript提供運行的上下文環境
JSValue:JavaScript和Objective-C數據和方法的橋梁
凡事添加了JSExport協議的協議,所規定的方法變量等,就會對js開放,我們可以通過JSContext調用到。
@protocol JSObjcDelegate <JSExport>
- (void)callCamera;
- (void)share:(NSString *)shareString;
@end
@interface ViewController : UIViewController
<UIWebViewDelegate,
JSObjcDelegate>
@property (nonatomic, strong) JSContext *jsContext;
@property (weak, nonatomic) IBOutlet UIWebView *webView;
@end
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSURL *url = [[NSBundle mainBundle] URLForResource:@"test" withExtension:@"html"];
[self.webView loadRequest:[[NSURLRequest alloc] initWithURL:url]];
self.webView.delegate = self;
}
#pragma mark - UIWebViewDelegate
- (void)webViewDidFinishLoad:(UIWebView *)webView {
self.jsContext = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
self.jsContext[@"Toyun"] = self;
self.jsContext.exceptionHandler = ^(JSContext *context, JSValue *exceptionValue) {
context.exception = exceptionValue;
NSLog(@"異常信息:%@", exceptionValue);
};
}
#pragma mark - JSObjcDelegate
- (void)callCamera {
NSLog(@"callCamera");
// 獲取到照片之後在回調js的方法picCallback把圖片傳出去
JSValue *picCallback = self.jsContext[@"picCallback"];
[picCallback callWithArguments:@[@"photos"]];
}
- (void)share:(NSString *)shareString {
NSLog(@"share:%@", shareString);
// 分享成功回調js的方法shareCallback
JSValue *shareCallback = self.jsContext[@"shareCallback"];
[shareCallback callWithArguments:nil];
}
@end
自定義JSObjcDelegate協議,而且此協議必須遵守JSExport這個協議,自定義協議中的方法就是暴露給web頁麵的方法:callCamera和share方法。
self.jsContext[@"Toyun"] = self;即把self賦值為名為Toyun的橋梁對象,則H5裏麵調用Toyun對象方法,即為此viewController處的方法。
在JavaStript調用完本地應用的方法做完相對應的事情之後,又回調了JavaStript中對應的方法,從而實現了web頁麵和本地應用之間的通訊。
最後更新:2017-08-13 22:34:14