工作中遇到的JS交互問題,稍微整理一下,留下來以備以後查用
JavaScriptCore.framework提供兩種方法交互方法,
一種是基於block的交互,
一種是基於協議的交互
0.導入JavaScriptCore.framework(就是在building phases裏添加庫)
基於協議實現的JS與webView交互
1.定義協議,示例代碼如下:
// ZSJSDelegate.h
#import <JavaScriptCore/JavaScriptCore.h>
@protocol ZSJSDelegate <JSExport>
//JS從iOS獲取數據
- (NSString *)postInfoFromWebView;
//iOS從JS獲取數據
- (void)postInfoFromJS:(NSString *)info;
//iOS從JS獲取數據,多參數拼接的情況
- (void)postNameFromJS:(NSString *)name andInfo:(NSString *)info;
@end
2.創建交互對象,遵守上述協議,實現協議方法,示例代碼如下:
// ZSJSObject.h
#import <Foundation/Foundation.h>
#import "ZSJSDelegate.h"
@interface ZSJSObject : NSObject
@end
// ZSJSObject.m
#import "ZSJSObject.h"
@interface ZSJSObject ()<ZSJSDelegate>
@end
@implementation ZSJSObject
- (NSString *)postInfoFromWebView
{
return @"infoForm_iOS";
}
- (void)postInfoFromJS:(NSString *)info
{
NSLog(@"info:%@", info);
}
- (void)postNameFromJS:(NSString *)name andInfo:(NSString *)info
{
NSLog(@"name:%@, info:%@", name, info);
}
@end
3.在webView中實現交互,示例代碼如下:
// ViewController.m
#import "ViewController.h"
#import "ZSJSObject.h"
@interface ViewController ()<UIWebViewDelegate>
@end
@implementation ViewController
{
UIWebView *_webView;
JSContext *_context;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self createWebView];
}
- (void)createWebView
{
_webView = [[UIWebView alloc]initWithFrame:self.view.bounds];
[self.view addSubview:_webView];
_webView.backgroundColor = [UIColor lightGrayColor];
_webView.delegate = self;
NSURL *url = [NSURL URLWithString:@"https://www.baidu.com/"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[_webView loadRequest:request];
//爲什麼這麼寫,我也不懂,希望有大神解惑
_context = [_webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
_context[@"jsObject"] = [[ZSJSObject alloc]init];
}
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
//網頁加載完成之後兩秒鐘,進行JS測試
[self performSelector:@selector(testJS) withObject:nil afterDelay:2.0f];
}
//測試交互,手動寫三個JS語句進行調用協議定義的方法
- (void)testJS
{
//JS從iOS獲取數據,通過返回值將數據傳道JS
[_context evaluateScript:@"alert(jsObject.postInfoFromWebView());"];
//本地從JS獲取數據,通過參數將數據傳遞到iOS
[_context evaluateScript:@"jsObject.postInfoFromJS('infoFromJS');"];
//多個參數拼接的規則:第二個參數名大寫首字母
[_context evaluateScript:@"jsObject.postNameFromJSAndInfo('nameFromJS','info');"];
}
基於block實現的JS與iOS交互
【注意】:比協議實現的步驟簡單,但是容易出現控制器無法釋放的問題,對內存要求不高的可以忽略
直接上示例代碼:
// JSWithBlockViewController.m
#import "JSWithBlockViewController.h"
#import <JavaScriptCore/JavaScriptCore.h>
@interface JSWithBlockViewController ()<UIWebViewDelegate>
@end
@implementation JSWithBlockViewController
{
UIWebView *_webView;
JSContext *_context;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self createWebView];
}
- (void)createWebView
{
_webView = [[UIWebView alloc]initWithFrame:self.view.bounds];
[self.view addSubview:_webView];
_webView.backgroundColor = [UIColor lightGrayColor];
_webView.delegate = self;
NSURL *url = [NSURL URLWithString:@"https://www.baidu.com/"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[_webView loadRequest:request];
//爲什麼這麼寫,我也不懂,希望有大神解惑
_context = [_webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
//JS從iOS獲取數據的實現
_context[@"postInfoFromWebView"] = ^() {
return @"infoFrom_iOS(block)";
};
//iOS從JS獲取數據的實現
_context[@"postInfoFromJS"] = ^() {
NSArray *args = [JSContext currentArguments];
for (JSValue *jsVal in args) {
NSString *str = jsVal.toString;
NSLog(@"arg:%@", str);
}
};
}
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
//網頁加載完成之後兩秒鐘,進行JS測試
[self performSelector:@selector(testJS) withObject:nil afterDelay:2.0f];
}
//測試交互,手動寫三個JS語句進行調用協議定義的方法
- (void)testJS
{
//JS從iOS獲取數據,通過返回值將數據傳到JS
[_context evaluateScript:@"alert(postInfoFromWebView());"];
//本地從JS獲取數據,通過參數將數據傳遞到iOS
[_context evaluateScript:@"postInfoFromJS('infoFromJS');"];
[_context evaluateScript:@"postInfoFromJS('nameFromJS','info');"];
}
基本上就這些,有什麼不妥的可以聯繫我。