iOS与H5交互的坑

iOS 专栏收录该内容
98 篇文章 0 订阅

之前的博客写过使用<JavaScriptCore/JavaScriptCore.h>库来实现与H5的交互,但是在项目中还是遇到了一些不得不踩的坑。在这里将我遇到的问题以及参考网上几位大神的解决方案列举出来,如果有更好的办法,欢迎讨论指正。在阅读本博客前,请参阅我之前的《iOS与H5交互》

一、问题一:在webView中加载H5界面,webView中的H5一级界面可以轻松实现oc与js方法互调,但如果在H5界面上进入二级界面,二级界面中再使用之前方法来交互就会失效。如图:左图为H5一级界面,右图为二级界面。

    

解决办法:

第一步:在控制器中声明两个变量,isNotFirstLoad用来记录webView是否是第一次加载网页;loadCount计数器,用来记录网页转跳次数,做返回处理。

第二步:实现- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType方法,代码如下:

- (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。

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
<p> <span style="font-size:14px;color:#337FE5;">【为什么学爬虫?】</span> </p> <p> <span style="font-size:14px;">       1、爬虫入手容易,但是深入较难,如何写出高效率爬虫,如何写出灵活性高可扩展爬虫都是一项技术活。另外在爬虫过程中,经常容易遇到被反爬虫,比如字体反爬、IP识别、验证码等,如何层层攻克难点拿到想要数据,这门课程,你都能学到!</span> </p> <p> <span style="font-size:14px;">       2、如果是作为一个其他行业开发者,比如app开发,web开发,学习爬虫能让你加强对技术认知,能够开发出更加安全软件和网站</span> </p> <p> <br /> </p> <span style="font-size:14px;color:#337FE5;">【课程设计】</span> <p class="ql-long-10663260"> <span> </span> </p> <p class="ql-long-26664262" style="font-size:11pt;color:#494949;"> 一个完整爬虫程序,无论大小,总体来说可以分成三个步骤,分别是: </p> <ol> <li class="" style="font-size:11pt;color:#494949;"> 网络请求:模拟浏览器行为从网上抓取数据。 </li> <li class="" style="font-size:11pt;color:#494949;"> 数据解析:将请求下来数据进行过滤,提取我们想要数据。 </li> <li class="" style="font-size:11pt;color:#494949;"> 数据存储:将提取到数据存储到硬盘或者内存中。比如用mysql数据库或者redis等。 </li> </ol> <p class="ql-long-26664262" style="font-size:11pt;color:#494949;"> 那么本课程也是按照这几个步骤循序渐进进行讲解,带领学生完整掌握每个步骤技术。另外,因为爬虫多样性,在爬取过程中可能会发生被反爬、效率低下等。因此我们又增加了两个章节用来提高爬虫程序灵活性,分别是: </p> <ol> <li class="" style="font-size:11pt;color:#494949;"> 爬虫进阶:包括IP代理,多线程爬虫,图形验证码识别、JS加密解密、动态网页爬虫、字体反爬识别等。 </li> <li class="" style="font-size:11pt;color:#494949;"> Scrapy和分布式爬虫:Scrapy框架、Scrapy-redis组件、分布式爬虫等。 </li> </ol> <p class="ql-long-26664262" style="font-size:11pt;color:#494949;"> 通过爬虫进阶知识点我们能应付大量反爬网站,而Scrapy框架作为一个专业爬虫框架,使用他可以快速提高我们编写爬虫程序效率和速度。另外如果一台机器不能满足你需求,我们可以用分布式爬虫让多台机器帮助你快速爬取数据。 </p> <p style="font-size:11pt;color:#494949;">   </p> <p class="ql-long-26664262" style="font-size:11pt;color:#494949;"> 从基础爬虫到商业化应用爬虫,本套课程满足您所有需求! </p> <p class="ql-long-26664262" style="font-size:11pt;color:#494949;"> <br /> </p> <p> <br /> </p> <p> <span style="font-size:14px;background-color:#FFFFFF;color:#337FE5;">【课程服务】</span> </p> <p> <span style="font-size:14px;">专属付费社群+定期答疑</span> </p> <p> <br /> </p> <p class="ql-long-24357476"> <span style="font-size:16px;"><br /> </span> </p> <p> <br /> </p> <p class="ql-long-24357476"> <span style="font-size:16px;"></span> </p>
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值