ios标准页面调用HTML5页面和HTML5调用ios的函数

简介: ios标准页面调用HTML5页面和HTML5调用ios的函数

ios原生态页面相对于HTML5页面具有渲染效果好,流畅,省流量的特点,但是比较难实现动态加载多个页面(如支付宝),动态修改页面布局。

我们使用的是WebViewJavascriptBridge这个第三方控件。

html5有四种加载方式。

第一种,在h5页面加入工程,本地加载方式。

第二种,判断本地是否有h5页面文件,若没有向服务发送文件请求,下载h5页面,然后本地加载。

第三种,不经过服务器以加载页面的方式加载页面,它是一种同步加载方式。

第四种,向服务器发送请求获得html5页面的加载方式,它是一种异步加载方式。


通过下面的方法加载本地HTML5页面。若本地没有HTML5页面文件,通过向服务器发送请求接收HTML5页面文件,让后加载本地HTML5页面。缺点不能实时更新页面,服务器变更不能在本地体现,不能统计页面点击量,不能识别是谁点击的页面,好处是省流量,一次下载一劳永逸。

        NSString* htmlPath = [[NSBundle mainBundle] pathForResource:html ofType:@"html"];
        NSString* appHtml = [NSString stringWithContentsOfFile:htmlPath encoding:NSUTF8StringEncoding error:nil];
        NSURL *baseURL = [NSURL fileURLWithPath:html];
        [webView loadHTMLString:appHtml baseURL:baseURL];

第三种方案,实现很简单,估计很多app都是用这种方法,但是这种方案难以对各种异常进行友好提示,并且是同步加载方式,堵塞整个流程。典型代码实现:

    NSURLRequest* request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10.0];
    [self.webView loadRequest:request];

下面都是采用第四种实现方案,这个是HTML5的源代码,bridge.callHandler(‘endMyDegreeIOS’,data, function(responseData) {});这个代码中endMyDegreeIOS是调用的IOS的函数。通过这样的代码可以实现HTML5调用IOS的代码。它的本质

是通过回调函数找到IOS的函数的。

<!doctype html>
<html lang="en">
 <head>
  <meta charset="UTF-8">
  <title>Document</title>
 </head>
 <script type="text/javascript" src="http://172.16.28.165:8080/fhl/statics/easyui/jquery-1.4.4.min.js"></script>
 <body>
    <script>
    /*
     * IOS下 连接HTML的代码
     */
    function connectWebViewJavascriptBridge(callback) {
         if (window.WebViewJavascriptBridge) {
               callback(WebViewJavascriptBridge)
         } else {
               document.addEventListener('WebViewJavascriptBridgeReady', function() {
                    callback(WebViewJavascriptBridge)
               }, false)
         }
    }
    connectWebViewJavascriptBridge (function(bridge) {

        // init方法是把数据传给开发
        // 再调用responseCallback(data)
        bridge.init(function(message, responseCallback) {
               var data = { 'Javascript Responds 111111111':'Wee!' };  // 必须是json格式的
               responseCallback(data)
        });
        var data = {"message":"找不到运费信息"};
        bridge.callHandler('endMyDegreeIOS',data, function(responseData) {});
    });

    </script>
 </body>
</html>

下面是一个完整的调用HTML5页面。

_bridge = [WebViewJavascriptBridge bridgeForWebView:self.webView webViewDelegate:self handler:^(id data, WVJBResponseCallback responseCallback) 这个是HTML5页面回调用的,没有这个一切免谈了,一切异常都处理不了,HTML5根本找不到ios的函数,只能处理正常加载成功的情况。

同过[webView loadRequest:request];可以向服务器发送请求HTML5页面。

NSURLRequest *request = [User getBookPageRequest];这个设置向服务发送的请求,关键是拼接 http参数字符串。[webView loadRequest:request];这个就是加载服务器返回的html5页面。

//
//  InstructionViewController.m
//  FHL
//
//  Created by panume on 14-10-21.
//  Copyright (c) 2014年 JUEWEI. All rights reserved.
//

#import "InstructionViewController.h"
#import "WebViewJavascriptBridge.h"
#import "SecondWebViewController.h"
#import "LoginViewController.h"
#import "AnimatedView.h"
#import "GlobalVariable.h"
#import "Reachability.h"

@interface InstructionViewController () <UIWebViewDelegate>
@property (nonatomic, strong) WebViewJavascriptBridge *bridge;
@property (nonatomic, strong) UIWebView *webView;
@property (nonatomic, strong) AnimatedView *animatedView;
@property (nonatomic, strong) UIActivityIndicatorView *indicatorView;

@end

@implementation InstructionViewController

- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {

    }
    return self;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.

    self.animatedView = [[AnimatedView alloc] initWithFrame:CGRectMake(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT) imageName:@"logo_watermark_run" remark:@"正在努力加载中"];

    __weak __typeof(self)weakSelf = self;
    self.animatedView.touchAction = ^(void){
        [weakSelf loadExamplePage:weakSelf.webView];
    };
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    self.view.backgroundColor = [UIColor colorWithHex:0xf5f5f5];

    if (!self.webView) {
        self.webView = [[UIWebView alloc] initWithFrame:self.view.bounds];
        self.webView.backgroundColor = [UIColor whiteColor];
        [self.view addSubview:self.webView];

        if (!self.indicatorView) {
            self.indicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
            self.indicatorView.frame = CGRectMake(0, 0, 40, 40);
            self.indicatorView.center = self.webView.center;
            self.indicatorView.hidesWhenStopped = YES;
            [self.view addSubview:self.indicatorView];
            [self.indicatorView startAnimating];
        }


        [WebViewJavascriptBridge enableLogging];

        _bridge = [WebViewJavascriptBridge bridgeForWebView:self.webView webViewDelegate:self handler:^(id data, WVJBResponseCallback responseCallback) {
            FLDDLogDebug(@"ObjC received message from JS: %@", data);
            responseCallback(@"Response for message from ObjC");
        }];

        [_bridge registerHandler:@"reloadPage" handler:^(id data, WVJBResponseCallback responseCallback) {
            FLDDLogDebug(@"reloadPage");
            [self reLoginReloadPage];
        }];

        [_bridge registerHandler:@"fhlSecondCallback" handler:^(id data, WVJBResponseCallback responseCallback) {
            FLDDLogDebug(@"testObjcCallback called: %@", data);

            SecondWebViewController *secondWebVC = [[SecondWebViewController alloc] init];

            NSString *html = [data toString];
            if ([html isEqualToString:@"shouce"]) {

                secondWebVC.title = @"配送手册";
                secondWebVC.type = SWebViewTypeNotebook;

            }
            else if ([html isEqualToString:@"learn"])
            {
                secondWebVC.title = @"在线培训";
                secondWebVC.type = SWebViewTypeLearn;
            }
            [self.navigationController pushViewController:secondWebVC animated:YES];

            responseCallback(@"Response from testObjcCallback");
        }];

        [_bridge send:@"123"];

        [self loadExamplePage:self.webView];
    }
}

- (void)loadExamplePage:(UIWebView*)webView
{

    if (self.animatedView.superview) {
        [self.animatedView removeFromSuperview];
        self.animatedView.hidden = NO;

        if (self.indicatorView.superview) {
            self.indicatorView.hidden = NO;
            self.indicatorView.center = self.webView.center;
            [self.view bringSubviewToFront:self.indicatorView];
            [self.indicatorView startAnimating];
        }
    }

    NSURLRequest *request = [User getBookPageRequest];
    if(request != nil)
    {
        [webView loadRequest:request];
    }
}

-(void)reLoginReloadPage
{
    [[UIApplication sharedApplication] unregisterForRemoteNotifications];//用户退出登录后,取消推送的注册,登录时register

    if ([AppManager boolValueForKey:@"isFirstReLogin"]) {

        [AppManager setUserBoolValue:NO key:@"isFirstReLogin"];

        [self needLoginIn];
    }
}


- (void)needLoginIn
{
    [[User currentUser] removeUserInfo];
    NSString *phone = [AppManager valueForKey:@"telephone"];
    NSString *password = [AppManager valueForKey:@"password"];

    if (phone == nil || password == nil) {
        LoginViewController *loginViewController = [[LoginViewController alloc] init];
//        UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:loginViewController];
//        navigationController.navigationBar.barTintColor = [UIColor colorWithHex:0xf5f5f5];
//        [self.navigationController presentViewController:navigationController animated:YES completion:nil];
        [self.navigationController pushViewController:loginViewController animated:YES];
        return;
    }

    BOOL isRegister = [AppManager boolValueForKey:@"isRegister"];
    if (isRegister) {
        AppDelegate *delegate = (AppDelegate *)[UIApplication sharedApplication].delegate;

        for (UIViewController *viewController in delegate.navigationController.viewControllers) {
            if ([viewController isKindOfClass:[LoginViewController class]]) {
                [delegate.navigationController popToViewController:viewController animated:YES];
                return;
            }
        }

    }

    NSDictionary *params = @{@"courierTel": phone,
                             @"passwd" : password};

    [User reLoginWithParams:params block:^(NSArray *districts ,NSError *error) {

        if (error) {

            NSString *alert = @"账户在其他设备登录";

            UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil
                                                                message:alert
                                                               delegate:self
                                                      cancelButtonTitle:@"确定"
                                                      otherButtonTitles:nil, nil];
            alertView.tag = 1007;
            [alertView show];


        }
        else {
//            [[NSNotificationCenter defaultCenter] postNotificationName:HIT_HEART_NOTIFICATION object:nil userInfo:@{@"beginHit" : @(YES)}];
//            [[NSNotificationCenter defaultCenter] postNotificationName:UPDATE_LOCATION_NOTIFICATION object:nil];
            [[NSNotificationCenter defaultCenter] postNotificationName:PUSH_CONFIG_NOTIFICATION object:nil];
            [[NSNotificationCenter defaultCenter] postNotificationName:GET_MESSAGE_COUNT object:nil];


            [AppDelegate registerForRemoteNotification];
            [AppManager setUserBoolValue:YES key:@"isFirstReLogin"];
            NSURLRequest *request = [User getBookPageRequest];
            if(request != nil)
            {
                [self.webView loadRequest:request];
            }
        }

    }];
}


- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{

    if (alertView.tag == 1007) {

        if (buttonIndex == alertView.cancelButtonIndex) {
            [[UIApplication sharedApplication] unregisterForRemoteNotifications];

            [AppManager setUserBoolValue:YES key:@"NeedRefreshMes"];
//            [AppManager setUserBoolValue:YES key:@"NeedRefreshStage"];
            [AppManager setUserBoolValue:YES key:@"NeedRefreshHome"];
            [AppManager setUserBoolValue:NO key:@"HasShowHeader"];


            AppDelegate *delegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
            delegate.tabBarController.selectedIndex = 0;

            [delegate.tabBarController.navigationController popToRootViewControllerAnimated:NO];

            [AppManager setUserBoolValue:YES key:@"refreshCode"];

            LoginViewController *loginViewController = [[LoginViewController alloc] init];
//            UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:loginViewController];
//            navigationController.navigationBar.barTintColor = [UIColor colorWithHex:0xf5f5f5];
//            [delegate.tabBarController.navigationController presentViewController:navigationController animated:NO completion:nil];
            [delegate.tabBarController.navigationController pushViewController:loginViewController animated:YES];
        }
    }
}



#pragma mark - UIWebViewDelegate

- (void)webViewDidStartLoad:(UIWebView *)webView {
    FLDDLogDebug(@"webViewDidStartLoad");
    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
}

- (void)webViewDidFinishLoad:(UIWebView *)webView {
    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];

    FLDDLogDebug(@"webViewDidFinishLoad");
    [self.indicatorView stopAnimating];

     [_bridge send:@"123"];
}

- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];

    FLDDLogDebug(@"instruction wevView load error:%@", error);
    [self.indicatorView stopAnimating];

    if (self.animatedView) {
        self.animatedView.animatedState = AnimatedViewStateFailed;
        [self.view addSubview:self.animatedView];
    }

    if(NotReachable == g_networkStatus)
    {
//        [SVProgressHUD showErrorWithStatus:g_errorNoNetDes];
        [MBProgressHUD hudShowWithStatus:self : g_errorNoNetDes];
    }
    else
    {
        [MBProgressHUD hudShowWithStatus:self :[error localizedDescription]];
    }
}



@end

这个是用charles截获的请求。

http://test.zuixiandao.cn/fhl/phone/psy/toBookIOSJsonPhone.htm?visitTime=1437363928&phoneId=ios_120e438f-9757-451d-b980-0d87824b02eb&key=9CC427BB979A9C0550F9BFFC2BDDD173&cmdCode=8100&cmdCode=8100

这个是用charles截获的请求响应。

<!doctype html>
<html lang="en">
 <head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no" />
  <title>Document</title>
  <style>
     body,h1,h2,h3,h4,h5,h6,hr,p,blockquote,dl,dt,dd,ul,ol,li,pre,form,fieldset,legend,button,input,textarea,th,td{margin:0;padding:0;font-family:"Microsoft yahei";color:#000;}
    h1,h2,h3,h4,h5,h6{font-weight:500;}
    ul,ol,li{list-style:none;}
    i,em{font-style:normal}
    img{max-width:100%;}
    body{font-size:1em;background:#eee;}
    .book-container {width:100%;height:100%;background:#eee;overflow:hidden;}
    .book-header{height:100%;overflow:hidden;}
    .book-nav {width:100%;margin-top:-4px;overflow:hidden;}

    .book-content{width:100%;background:#fff;overflow:hidden;}
    .book-content ul{width:100%;margin:0 auto;overflow:hidden;}
    .book-content li {height:66px;line-height:66px;border-bottom:1px solid #e0e0e0;overflow:hidden;}
    .book-content li.last-col{border-bottom:none;}
    .book-content li a{display:block;height:66px;text-decoration:none;overflow:hidden;}
    .book-content li em{float:left;margin-left:12px;margin-top:11px;font-size:1.125em;height:44px;line-height:44px;color:#333333;}

    .book-content li .notebook-icon {
        float:left;
        margin-top:12px;
        background:url("http://test.zuixiandao.cn/fhl/templates/Html/notebook.png") no-repeat 0 5px;
        width:48px;
        height:48px;
        background-size:32px 32px;
        margin-left:26px;
    }
    .book-content li .online-icon {
        float:left;
        margin-top:12px;
        background:url("http://test.zuixiandao.cn/fhl/templates/Html/train_icon.png") no-repeat 0 5px;
        width:48px;
        height:48px;
        background-size:32px 32px;
        margin-left:26px;
    }
    .book-content .last-col i, .book-content .public-icon i{
        float:right;
        padding-right:16px;
        margin-top:23px;
        background:url("http://test.zuixiandao.cn/fhl/templates/Html/jiantou.png") no-repeat 0px 0;
        width:15px;
        height:25px;
        background-size:12px 20px;
    }

    .more-content {width:100%;height:66px;line-height:66px;border-top:1px solid #d7d7d7;overflow:hidden;}
    .more-content i{float:left;height:66px;width:66px;margin-top:0px;background:url("http://test.zuixiandao.cn/fhl/templates/Html/more-icon.png") no-repeat;background-size:66px 66px;}
    .more-content span{float:left;margin-left:19px;font-size:1.125em;color:#f2764f;}
  </style>
 </head>
 <body>
    <div class="book-container">
        <div class="book-header">
            <img src="http://test.zuixiandao.cn/fhl/templates/Html/book-top.png" width="100%"/>
        </div>
        <div class="book-nav">

            <div id="tab-contnetWrapper">
                <div class="book-content">
                    <ul>
                        <li class="public-icon">
                            <a id="online-train">
                                <span class="online-icon"></span>
                                <em>在线培训</em>
                                <i></i>
                            </a>
                        </li>
                        <li class="last-col">
                            <a id="bookId">
                                <span class="notebook-icon"></span>
                                <em>配送手册</em>
                                <i></i>
                            </a>
                        </li>
                    </ul>
                    <div class="more-content">
                        <i></i><span>更多内容,敬请期待哦~</span>
                    </div>
                </div>
            </div>
        </div>
    </div>


    <script>

       function connectWebViewJavascriptBridge(callback) {
         if (window.WebViewJavascriptBridge) {
           callback(WebViewJavascriptBridge)
         } else {
            document.addEventListener('WebViewJavascriptBridgeReady', function() {
            callback(WebViewJavascriptBridge)
             }, false)
         }
       }

        connectWebViewJavascriptBridge(function(bridge) {
            var uniqueId = 1
           function log(message, data) {
           var log = document.getElementById('log')
           var el = document.createElement('div')
           el.className = 'logLine'
           el.innerHTML = uniqueId++ + '. ' + message + ':<br/>' + JSON.stringify(data)
           if (log.children.length) { log.insertBefore(el, log.children[0]) }
           else { log.appendChild(el) }
           }

        bridge.init(function(message, responseCallback) {
            var data = { 'Javascript Responds 111111111':'Wee!' }
            responseCallback(data)
        })


        bridge.registerHandler('fhlFirstJavascriptHandler', function(data, responseCallback) {
                               responseCallback(data)

        });
        var bookId = document.getElementById("bookId"),
            trainId = document.getElementById("online-train");
        bookId.addEventListener('touchstart',function(){
            var data = 'shouce'

            bridge.callHandler('fhlSecondCallback',data, function(responseData) {
            })
        })

        trainId.addEventListener('touchstart',function(){
            var data = 'learn'

            bridge.callHandler('fhlSecondCallback',data, function(responseData) {
            })
        })                                

    })
    </script>

 </body>
</html>


目录
相关文章
|
12天前
|
Web App开发 监控 JavaScript
JS 鼠标框选(页面选择)时返回对应的 HTML 或文案内容
JS 鼠标框选(页面选择)时返回对应的 HTML 或文案内容 当用户进行鼠标框选选择了页面上的内容时,把选择的内容进行上报。 分为以下几点: 选择文案时 选择图片、svg、iframe、video、audio 等标签时 选择 input、select、textarea 等标签时 选择 input、textarea 标签内容时 选择类似 &nbsp; 字符时 键盘全选时 鼠标右键选择 以上各模块结合时 当包含标签的时候,返回 html 结构,只有文本时返回文本内容
13 1
|
12天前
|
存储 移动开发 前端开发
Web网页制作-知识点(1)——HTML5介绍、HTML5的DOCTYPE声明、HTML基本骨架、标题标签、段落 换行、水平线图片图片路径、超链接
Web网页制作-知识点(1)——HTML5介绍、HTML5的DOCTYPE声明、HTML基本骨架、标题标签、段落 换行、水平线图片图片路径、超链接
11 0
|
14天前
|
数据采集 移动开发 搜索推荐
HTML基础-HTML5新增语义标签:解锁网页结构新维度
【6月更文挑战第5天】本文介绍了HTML5的语义标签,旨在提升网页结构化和可访问性。核心语义标签包括`&lt;header&gt;`、`&lt;nav&gt;`、`&lt;main&gt;`、`&lt;article&gt;`、`&lt;section&gt;`、`&lt;aside&gt;`、`&lt;footer&gt;`、`&lt;figure&gt;`和`&lt;figcaption&gt;`。常见问题包括滥用标签作布局工具、忽略`&lt;main&gt;`、不恰当嵌套和忽视辅助功能。
|
15天前
404错误页面源码,简单实用的html错误页面模板
小编精心准备一款404错误页面源码,简单实用的html错误页面模板,简单大气的页面布局,可以使用到不同的网站中,相信大家一定会喜欢的
9 2
404错误页面源码,简单实用的html错误页面模板
|
20天前
|
前端开发
html编写登录页面练习
html编写登录页面练习
24 0
|
20天前
html编写注册页面
html编写注册页面
21 0
|
21天前
|
前端开发 JavaScript
基于Html对父页面打开子页面Dialog()的使用
作者在使用基于QUI的前端项目中遇到一个问题:无法在Dialog组件中提交后刷新列表页面。经过搜索和努力,找到了解决方案。通过创建新的`top.Dialog()`,设置相关属性如标题、URL、尺寸,并在OK事件中调用子页面的提交方法及刷新列表的方法实现了需求。提供的代码示例展示了如何打开编辑窗体并处理提交事件以刷新列表。
|
21天前
|
Web App开发 编解码 移动开发
HTML页面关于高分屏的设置
该文章讲述了HTML页面在高分屏环境下遇到的问题,主要涉及`window.innerWidth`和`window.innerHeight`等参数返回物理设备宽度而非实际像素宽度,导致Chrome和Firefox在PC及Android端表现不一致。为解决兼容性问题,文章建议在HTML头部添加`viewport`元标签,设置`width=device-width, initial-scale=1.0`,以确保适配不同设备的高分屏。
|
25天前
|
移动开发 网络协议 安全
HTML5页面被运营商DNS问题及解决方案,app中h5页面源码的获取
HTML5页面被运营商DNS问题及解决方案,app中h5页面源码的获取
84 4
|
XML JavaScript 前端开发
HTML页面基本结构和加载过程
HTML页面基本结构和加载过程
226 0
HTML页面基本结构和加载过程