UIWebView、WKWebView与js的交互

最近项目里用到了web界面与js交互,项目使用的是UIWebView,但是会出现数据丢失的情况比较麻烦,使用WKWebView可以避免这种情况,下面就写一些web的基本使用,可能有些使用不当的地方,请指教。
* UIWebView
创建一个类文件,可以定义交互时的函数名,然后定义一个代理,在web界面调用进行相应的操作。
“`
//类的.h文件
# import

//类的.m文件
   #import "KQJSModel.h"
#import "KQPayTypeViewController.h"


@implementation KQJSModel

-(void)startPay:(int)amount Action:(NSString *)action Teamid:(NSString *)teamid
{
    NSLog(@"--------amount:%d---------action:%@------teamid:%@",amount,action,teamid);

    if (self.delegate && [self.delegate respondsToSelector:@selector(goToPayVC:action:teamid:)]) {
        [self.delegate goToPayVC:amount action:[NSString stringWithFormat:@"%@",action] teamid:[NSString stringWithFormat:@"%@",teamid]];
    }

}
@end
//web界面,在代理方法里注入方法名,
-(void)webViewDidStartLoad:(UIWebView *)webView
{


    //首先创建JSContext 对象(此处通过当前webView的键获取到jscontext)
    JSContext *context=[webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];

    //第二种情况,js是通过对象调用的,我们假设js里面有一个对象 testobject 在调用方法
    //首先创建我们新建类的对象,将他赋值给js的对象

    KQJSModel *testJO=[[KQJSModel alloc] init];
    testJO.delegate = self; //类的协议代理
    context[@"IOSApp"]=testJO;

    //        同样我们也用刚才的方式模拟一下js调用方法
    //            NSString *jsStr1=@"IOSApp.getBaseUrl()";
    //            [context evaluateScript:jsStr1];

}
-(void)webViewDidFinishLoad:(UIWebView *)webView
{

    //获取网页标题

    NSString * htmlTitle = [webView stringByEvaluatingJavaScriptFromString:@"document.title"];;
    NSLog(@"-----网页标题---%@",htmlTitle);
    self.title = [NSString stringWithFormat:@"%@",htmlTitle];
    //首先创建JSContext 对象(此处通过当前webView的键获取到jscontext)
    JSContext *context=[webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];

    //第二种情况,js是通过对象调用的,我们假设js里面有一个对象 testobject 在调用方法
    //首先创建我们新建类的对象,将他赋值给js的对象

    KQJSModel *testJO=[[KQJSModel alloc] init];
    testJO.delegate = self;  //类的协议代理
    context[@"IOSApp"]=testJO;
}
//再调用KQJSModel类的代理方法,在代理方法里实现想要的进行的操作。
#pragma mark -- KQJSModelDelegate
-(void)goToPayVC:(int)amount action:(NSString *)action teamid:(NSString *)teamid
{
//进行界面跳转,刷新,一定要在主线程里,不然会崩溃
    dispatch_async(dispatch_get_main_queue(), ^{
        KQPayTypeViewController *pay = [[KQPayTypeViewController alloc] init];
        pay.money = [NSString stringWithFormat:@"%d",amount];
        pay.action = [NSString stringWithFormat:@"%@",action];
        pay.teamid = [NSString stringWithFormat:@"%@",teamid];
        if (![action isEqualToString:@""] && action != nil) {
            pay.vip = @"vip";
        }

        KQCommonNavController *nav = [[KQCommonNavController alloc]initWithRootViewController:pay];
        [self presentViewController:nav animated:YES completion:nil];
    });
}

以上就是UIWebView与js的交互,运行就可以进行相应的操作了。

  • WKWebView
    最近才看了WKWebView的使用,就感觉比UIWebView流畅写,然后自带的导航进度条,这个感觉很方便,下面是与js的简单的交互,有不正确的,请留言,谢谢~
  #import "ViewController.h"
#import <WebKit/WebKit.h>



#define kScreenWidth [UIScreen mainScreen].bounds.size.width
#define kScreenHeight [UIScreen mainScreen].bounds.size.height

@interface ViewController ()<WKUIDelegate,WKNavigationDelegate,WKUIDelegate,WKScriptMessageHandler>

@property (nonatomic, strong) WKWebView *wkWebView;
@property (nonatomic, strong) WKWebViewConfiguration *wkConfig;

/*
 *1.添加UIProgressView属性
 */
@property (nonatomic, strong) UIProgressView *progressView;

@end

@implementation ViewController

#pragma mark - 初始化wkWebView

- (WKWebViewConfiguration *)wkConfig {
    if (!_wkConfig) {
        _wkConfig = [[WKWebViewConfiguration alloc] init];
        _wkConfig.allowsInlineMediaPlayback = YES;
        _wkConfig.allowsPictureInPictureMediaPlayback = YES;
         _wkConfig.processPool = [[WKProcessPool alloc] init];
        [_wkConfig.userContentController addScriptMessageHandler:self name:@"AppModel"];  //注入的js函数名,

    }
    return _wkConfig;
}

- (WKWebView *)wkWebView {
    if (!_wkWebView) {
        _wkWebView = [[WKWebView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, kScreenHeight) configuration:self.wkConfig];
        // 导航代理
        _wkWebView.navigationDelegate = self;
        // 与webview UI交互代理
        _wkWebView.UIDelegate = self;
        [self.view addSubview:_wkWebView];
    }
    return _wkWebView;
}


/*
 *6.在dealloc中取消监听
 */

- (void)dealloc {
    [self.wkWebView removeObserver:self forKeyPath:@"estimatedProgress"];
}

- (void)viewDidLoad {
    [super viewDidLoad];

  [self startLoad];

    /*
     *2.初始化progressView
     */
    self.progressView = [[UIProgressView alloc] initWithFrame:CGRectMake(0, 64, [[UIScreen mainScreen] bounds].size.width, 2)];
    self.progressView.backgroundColor = [UIColor blueColor];
    //设置进度条的高度,下面这句代码表示进度条的宽度变为原来的1倍,高度变为原来的1.5倍.
    self.progressView.transform = CGAffineTransformMakeScale(1.0f, 1.5f);
    [self.view addSubview:self.progressView];

    /*
     *3.添加KVO,WKWebView有一个属性estimatedProgress,就是当前网页加载的进度,所以监听这个属性。
     */
    [self.wkWebView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil];

    UIButton *bavkBtn = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 16, 20)];

    [bavkBtn setImage:[UIImage imageNamed:@"navback"] forState:UIControlStateNormal];
    [bavkBtn addTarget:self action:@selector(back) forControlEvents:UIControlEventTouchUpInside];
    UIBarButtonItem *left = [[UIBarButtonItem alloc] initWithCustomView:bavkBtn];
    self.navigationItem.leftBarButtonItem = left;
}
- (void)back{
    if ([self.wkWebView canGoBack]) {
        [self.wkWebView goBack];
    }
}

#pragma mark - start load web

- (void)startLoad {
    NSString *urlString = @"http://www.baidu.com";
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlString]];
    request.timeoutInterval = 15.0f;
    [self.wkWebView loadRequest:request];
}

#pragma mark - 监听

/*
 *4.在监听方法中获取网页加载的进度,并将进度赋给progressView.progress
 */

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {
    if ([keyPath isEqualToString:@"estimatedProgress"]) {
        self.progressView.progress = self.wkWebView.estimatedProgress;
        if (self.progressView.progress == 1) {
            /*
             *添加一个简单的动画,将progressView的Height变为1.4倍
             *动画时长0.25s,延时0.3s后开始动画
             *动画结束后将progressView隐藏
             */
            __weak typeof (self)weakSelf = self;
            [UIView animateWithDuration:0.25f delay:0.3f options:UIViewAnimationOptionCurveEaseOut animations:^{
                weakSelf.progressView.transform = CGAffineTransformMakeScale(1.0f, 1.4f);
            } completion:^(BOOL finished) {
                weakSelf.progressView.hidden = YES;

            }];
        }
    }else{
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}

#pragma mark - WKWKNavigationDelegate Methods

/*
 *5.在WKWebViewd的代理中展示进度条,加载完成后隐藏进度条
 */

//开始加载
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation {
    NSLog(@"开始加载网页");
    //开始加载网页时展示出progressView
    self.progressView.hidden = NO;
    //开始加载网页的时候将progressView的Height恢复为1.5倍
    self.progressView.transform = CGAffineTransformMakeScale(1.0f, 1.5f);
    //防止progressView被网页挡住
    [self.view bringSubviewToFront:self.progressView];



}

//加载完成
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
    NSLog(@"加载完成");


}

//加载失败
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error {
    NSLog(@"加载失败");
    //加载失败同样需要隐藏progressView
    self.progressView.hidden = YES;
}

//页面跳转
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
    //允许页面跳转
    NSLog(@"%@",navigationAction.request.URL);
    decisionHandler(WKNavigationActionPolicyAllow);
}
#pragma mark - WKUIDelegate
- (void)webViewDidClose:(WKWebView *)webView {
    NSLog(@"%s", __FUNCTION__);
}

// 在JS端调用alert函数时,会触发此代理方法。
// JS端调用alert时所传的数据可以通过message拿到
// 在原生得到结果后,需要回调JS,是通过completionHandler回调
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler {
    NSLog(@"%s", __FUNCTION__);
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"alert" message:@"JS调用alert"                 preferredStyle:UIAlertControllerStyleAlert];
    [alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        completionHandler();
    }]];

    [self presentViewController:alert animated:YES completion:NULL];
    NSLog(@"%@", message);
}

// JS端调用confirm函数时,会触发此方法
// 通过message可以拿到JS端所传的数据
// 在iOS端显示原生alert得到YES/NO后
// 通过completionHandler回调给JS端
- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler {
    NSLog(@"%s", __FUNCTION__);

    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"confirm" message:@"JS调用confirm" preferredStyle:UIAlertControllerStyleAlert];
    [alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        completionHandler(YES);
    }]];
    [alert addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
        completionHandler(NO);
    }]];
    [self presentViewController:alert animated:YES completion:NULL];

    NSLog(@"%@", message);
}

// JS端调用prompt函数时,会触发此方法
// 要求输入一段文本
// 在原生输入得到文本内容后,通过completionHandler回调给JS
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * __nullable result))completionHandler {
    NSLog(@"%s", __FUNCTION__);

    NSLog(@"%@", prompt);
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"textinput" message:@"JS调用输入框" preferredStyle:UIAlertControllerStyleAlert];
    [alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
        textField.textColor = [UIColor redColor];
    }];

    [alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        completionHandler([[alert.textFields lastObject] text]);
    }]];

    [self presentViewController:alert animated:YES completion:NULL];
}
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值