iOS与H5交互 以及问题记录

来源:互联网 发布:水暖毯和电热毯 知乎 编辑:程序博客网 时间:2024/04/20 11:39

前提:在iOS控制器中加载UIWebView,设置代理,遵守UIWebViewDelegate协议。
这里写图片描述

一、iOS调用JS方法

通过iOS调用JS代码实现起来比较方便直接调用UIWebView的方法- (nullable NSString )stringByEvaluatingJavaScriptFromString:(NSString )script;

1.查询标签

  // 查询标签  NSString *str = @"var word = document.getElementById('word');"                       @"alert(word.innerHTML)";

[webView stringByEvaluatingJavaScriptFromString:str];

2.为网页添加标签:
NSString *str = @”var img = document.createElement(‘img’);”
“img.src = ‘icon5.jpg’;”
“img.width = 300;”
“img.heigth = 100;”
“document.body.appendChild(img);”;
[webView stringByEvaluatingJavaScriptFromString:str];

3.删除网页标签:
// 删除标签
NSString *str1 = @”var word = document.getElementById(‘word’);”
@”word.remove();”;
[webView stringByEvaluatingJavaScriptFromString:str1];

4.更改标签:
// 更改
NSString *str2 = @”var change = document.getElementsByClassName(‘change’)[0];”
“change.innerHTML = ‘hello’;”;
NSString *result = [webView stringByEvaluatingJavaScriptFromString:str2];

HTML端代码:

  <!DOCTYPE html>     <html lang="en">     <head>            <meta charset="UTF-8">            <title>iOS和H5交互</title>     </head>     <body>            <p id="word">6666666666</p>            <ul>                 <li class="change">111111</li>                 <li class="haha">222222</li>                 <li>333333</li>                 <li>444444</li>            </ul>            <input class="name" placeholder="请输入密码">            <button onclick="buttonClick()">提交信息</button>    <script type="text/javascript">            alert('这个一个弹框');    </script>    </body>    </html>

二、JS调用iOS方法:

1.第一种方法比较简单,通过字符串的比对。这种方式iOS端代码比较简单,网页加载完成后后台需要重新定义网页url,将移动端需要的参数拼接到url上返回,或者按照和后台约定好的字段来进行字符串比对以达到调用iOS方法的目的。下面贴代码。

    oc代码:(需要实现webView的协议)     // 拦截协议头,调取系统摄像头     #pragma mark UIWebViewDelegate     - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:            (UIWebViewNavigationType)navigationType    {        NSString *str = request.URL.absoluteString;        if ([str containsString:@"wxd://"]) {             [self getImage];         }        return YES;     }    - (void)getImage {if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) { //调用相册//实例化控制器UIImagePickerController *picker = [[UIImagePickerController alloc] init];picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;picker.delegate = self;// 是否有图片选取框picker.allowsEditing = YES;[self presentViewController:picker animated:YES completion:nil];}}

HTML端代码:

   <!DOCTYPE html>   <html lang="en">          <head>          <meta charset="UTF-8">          <title>在html中调用oc的方法</title>          </head>          <body>                  <button onclick="getImage()">访问相册</button>          <script type="text/javascript">                  function getImage(){                        window.location.href = "wxd://getImage";                  }          </script>          </body>   </html>

2.第二种方法,JS直接用oc方法名来调用oc方法,类似于安卓.addJavascriptInterface(new JsObject(), “Android”)方法,头文件需要导入#import

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{    // isNotFirstLoad,记录webView是否第一次加载H5页面    if (isNotFirstLoad) {        CGRect frame = self.webView.frame;        [self.webView removeFromSuperview];        [self.animationView removeFromSuperview];        UIWebView *webView = [[UIWebView alloc] initWithFrame:frame];        webView.delegate = self;        [self.view addSubview:webView];        [webView loadRequest:request];        self.webView = webView;        //首先创建JSContext 对象(此处通过当前webView的键获取到jscontext)        JSContext *context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];        //创建JSTestObjext对象,赋值给js的对象        JSTestObjext *test = [JSTestObjext new];        test.delegate = self;        context[@"iOS"] = test;        isNotFirstLoad = NO;        return NO;    }    isNotFirstLoad = YES;    // 计数器,用来记录网页转跳次数,做返回处理    loadCount ++;    if (loadCount == 3) {        loadCount = 1;    }    return YES;}

在网页转跳二级界面的时候重新创建UIWebView和JSContext对象,将其当成一个新的网页,再使用JSContext对象来实现交互的时候就不会出现失效的情况。

第三步:此时在H5二级界面互调方法就不会有问题了,但新的问题又出现了,当点击返回按钮的时候如何返回上级界面。这时就要用到申明的loadCount成员变量了。具体代码写在自定义返回按钮的点击事件中,我在项目中导航栏是自定义的,重写返回按钮只需重写导航栏的leftBarButtonItem。代码如下:

- (void)viewDidLoad {    [super viewDidLoad];    self.title = self.webTitle;    // 设置导航栏返回按钮    self.navigationItem.leftBarButtonItem = [UIBarButtonItem itemWithIcon:@"nav_menu_back_02" highlighted:@"nav_menu_back_03" target:self action:@selector(backClick)];    [self createUI];}返回按钮点击事件代码如下:/** *  返回按钮点击事件 */- (void)backClick{    if (loadCount == 1) { // pop到上级VC        [self.navigationController popViewControllerAnimated:YES];    }else{ // 如果计数器为2,重新加载一级界面的url        NSURL *url = [NSURL URLWithString:self.url];        NSURLRequest *request = [NSURLRequest requestWithURL:url];        [self.webView loadRequest:request];}}

到此这个问题算是解决了。

二、问题二:
当H5界面中嵌套视频,在用手机横屏播放视频,点击右上角完成按钮退出播放界面的时候,会出现导航栏上移,与状态栏重合的bug。如图:

这里写图片描述
这里写图片描述
这里写图片描述
左图为正常进入H5界面的样子,点击视频播放按钮,进入视频播放界面,打开手机的竖排方向锁定,在手机横屏时候播放器会自动横屏播放,这时点击播放起左上角完成按钮活着右下角全屏按钮退出播放界面就会出现右图的bug,导航栏会向上移动,与状态栏重合。

解决方法:

第一步:在AppDelegate.h中增加一个属性值,用来设置是否允许横屏。代码如下:

#import <UIKit/UIKit.h>@interface AppDelegate : UIResponder <UIApplicationDelegate>@property (strong, nonatomic) UIWindow *window;/***  是否允许横屏的标记 */@property (nonatomic,assign)BOOL allowRotation;@end在AppDelegate.m中实现- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(nullable UIWindow *)window方法,具体代码如下:/** *  是否允许横屏 */- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(nullable UIWindow *)window{    if (self.allowRotation) {        return UIInterfaceOrientationMaskAll;    }    return UIInterfaceOrientationMaskPortrait;}

第二步:在加载webView的控制器中注册两个通知,通过监听UIWindow是否可见来判断视频播放器是否出现。在viewDidLoad中注册通知,见代码:

// 播放视频,监听视频播放器    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(begainFullScreen) name:UIWindowDidBecomeVisibleNotification object:nil];//进入全屏    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(endFullScreen) name:UIWindowDidBecomeHiddenNotification object:nil];//退出全屏实现通知方法:- (void)begainFullScreen{    AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];    appDelegate.allowRotation = YES;}/** *  退出全屏 */- (void)endFullScreen{    AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];    appDelegate.allowRotation = NO;    // 设置设备方向为竖排    if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]) {        SEL selector = NSSelectorFromString(@"setOrientation:");        NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[UIDevice instanceMethodSignatureForSelector:selector]];        [invocation setSelector:selector];        [invocation setTarget:[UIDevice currentDevice]];        int val = UIInterfaceOrientationPortrait;        [invocation setArgument:&val atIndex:2];        [invocation invoke];    }}

获取appDelegate需要引入头文件#import “AppDelegate.h”。这样就可以避免导航栏上移出现的bug。

1 0
原创粉丝点击