ios UIWebView與JS交互

工作中遇到的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');"];

}

基本上就這些,有什麼不妥的可以聯繫我。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章