• iOS下JS与OC互相调用(八)--Cordova简单实战


    新建工程,添加Cordova 关键类

    新建一个工程TestCordova 然后添加:confug.xml、Private 和 Public 两个文件夹里的所有文件

    然后build 发现报错

    为什么有会这么多报错呢?
    原因是Cordova 部分类中,并没有#import <Foundation/Foundation.h>,但是它们却使用了这个库里的NSArray、NSString 等类型。
    为什么用在终端里用命令行创建的工程就正常呢?
    那是因为用命令行创建的工程里已经包含了pch 文件,并且已经import 了 Foundation框架。截图为证:
     
    解决方案:创建一个pch文件,在pch文件里添加 #import <Foundation/Foundation.h> 
     
    再次编译、运行,依然报错,WTF!
    这里报错是因为Cordova的类引用错误,在命令行创建的工程里Cordova 是以子工程的形式加入到目标工程中,两个工程的命名空间不同,所以import 是用 类似这样的方式#import <Cordova/CDV.h>,但是我们现在是直接在目标工程里添加Cordova,所以要把#import <Cordova/CDV.h> 改为 #import "CDV.h"。其他的文件引用报错同理(比如:#import <Cordova/CDVCommandDelegate.h>会报错 只需改为 #import "CDVCommandDelegate.h"即可)。
     

    设置控制器,添加WebView

    1.加载本地HTML 
    加载本地HTML,为了方便起见,首先新建一个叫www的文件夹,然后在文件夹里放入要加载的HTML和cordova.js
    这里把www添加进工程时,需要注意勾选的是create foler references,创建的是蓝色文件夹:
     
    配置插件映射,config.xml:
     <feature name="TestPlugin">
            <param name="ios-package" value="TestPlugin" />
        </feature>
        <feature name="LocalStorage">
            <param name="ios-package" value="CDVLocalStorage" />
        </feature>
        <feature name="HandleOpenUrl">
            <param name="ios-package" value="CDVHandleOpenURL" />
            <param name="onload" value="true" />
        </feature>
        <feature name="IntentAndNavigationFilter">
            <param name="ios-package" value="CDVIntentAndNavigationFilter" />
            <param name="onload" value="true" />
        </feature>
        <feature name="GestureHandler">
            <param name="ios-package" value="CDVGestureHandler" />
            <param name="onload" value="true" />
        </feature>

    下面我再截图看下:

    OK,可以运行项目了:

     
     
     

    2.加载远程HTML 
    项目里一般都是这种情况,接口返回H5地址,然后用网页加载H5地址。
    只需要设置下 self.startPage就好了。

    这里有几个需要注意的地方:
    
    1:self.startPage的赋值,必须在[super viewDidLoad]之前,否则self.startPage 会被默认赋值为index.html。
    2:需要在config.xml中修改一下配置,否则加载远程H5时,会自动打开浏览器加载,
       需要添加的配置是:
    <allow-navigation href="https://*/*" />
    <allow-navigation href="http://*/*"  />
    3:远程H5中也要引用cordova.js文件。
    4:在 info.plist 中添加 App Transport Security Setting的设置。
    

    创建插件,配置插件

    在插件中实现JS要调用的原生方法,插件要继承自CDVPlugin,示例代码如下:

    //
    //  TestPlugin.h
    //  TestCordova
    //
    //  Created by Doman on 2017/7/14.
    //  Copyright © 2017年 Doman. All rights reserved.
    //
    
    #import "CDV.h"
    
    @interface TestPlugin :CDVPlugin
    
    - (void)scan:(CDVInvokedUrlCommand *)command;
    
    - (void)location:(CDVInvokedUrlCommand *)command;
    
    - (void)pay:(CDVInvokedUrlCommand *)command;
    
    - (void)share:(CDVInvokedUrlCommand *)command;
    
    - (void)changeColor:(CDVInvokedUrlCommand *)command;
    
    - (void)testController:(CDVInvokedUrlCommand*)command;
    
    @end

    配置插件,是在config.xml的widget中添加自己创建的插件,上面已经提到过。
    如下图所示:

    关于插件中方法的实现有几个注意点:
    如果你发现类似如下的警告: 

    THREAD WARNING: ['scan'] took '290.006104' ms. Plugin should use a background thread.

    那么直需要将实现改为如下方式即可:

    [self.commandDelegate runInBackground:^{
          // 这里是实现
    }];

    演示代码:

    - (void)scan:(CDVInvokedUrlCommand *)command
    {
        [self.commandDelegate runInBackground:^{
            dispatch_async(dispatch_get_main_queue(), ^{
                UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"原生弹窗" message:nil delegate:nil cancelButtonTitle:@"知道了" otherButtonTitles:nil, nil];
                [alertView show];
            });
        }];
    }

    如何获取JS 传过来的参数呢?
    CDVInvokedUrlCommand 参数,其实有四个属性,分别是argumentscallbackIdclassNamemethodName。其中arguments,就是参数数组。
    看一个获取参数的示例代码:

    - (void)share:(CDVInvokedUrlCommand *)command
    {
        NSUInteger code = 1;
        NSString *tip = @"分享成功";
        NSArray *arguments = command.arguments;
        if (arguments.count < 3) {;
            code = 2;
            tip = @"参数错误";
            NSString *jsStr = [NSString stringWithFormat:@"shareResult('%@')",tip];
            [self.commandDelegate evalJs:jsStr];
            return;
        }
    
        NSLog(@"从H5获取的分享参数:%@",arguments);
        NSString *title = arguments[0];
        NSString *content = arguments[1];
        NSString *url = arguments[2];
    
        // 这里是分享的相关代码......
    
        // 将分享结果返回给js
        NSString *jsStr = [NSString stringWithFormat:@"shareResult('%@','%@','%@')",title,content,url];
        [self.commandDelegate evalJs:jsStr];
    }

    如何将Native的结果回调给JS ?
    这里有两种方式:第一种是直接执行JS,调用UIWebView 的执行js 方法。示例代码如下:

    // 将分享结果返回给js
        NSString *jsStr = [NSString stringWithFormat:@"shareResult('%@','%@','%@')",title,content,url];
        [self.commandDelegate evalJs:jsStr];
    第二种是,使用Cordova 封装好的对象CDVPluginResult和API。
    使用这种方式时,在JS 调用原生功能时,必须设置执行成功的回调和执行失败的回调。即设置cordova.exec(successCallback, failCallback, service, action, actionArgs)的第一个参数和第二个参数。像这样:
    function locationClick() { 
        cordova.exec(setLocation,locationError,"HaleyPlugin","location",[]);
    }

    然后,Native 调用JS 的示例代码:

    - (void)location:(CDVInvokedUrlCommand *)command
    {
        // 获取定位信息......
    
        // 下一行代码以后可以删除
    //    NSString *locationStr = @"广东省深圳市南山区学府路XXXX号";
        NSString *locationStr = @"错误信息";
    
    //    NSString *jsStr = [NSString stringWithFormat:@"setLocation('%@')",locationStr];
    //    [self.commandDelegate evalJs:jsStr];
    
        [self.commandDelegate runInBackground:^{
            CDVPluginResult *result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:locationStr];
            [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
        }];
    }

    上面大家已经看到,插件类要继承CDVPlugin ,点进去看下:

    有个viewController,所以我门可以直接用.

    演示代码:

    - (void)testController:(CDVInvokedUrlCommand*)command
    {
        
        if (command.arguments.count>0) {
            //customize argument
            TestViewController* testViewCtrl = [[TestViewController alloc]init];
            [self.viewController presentViewController:testViewCtrl animated:YES completion:^{
                
                CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:@"我是OC回传的参数!"];
                [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
            }];
        }else{
            //callback
            CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"没有参数"];
            [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
        }
    
    }

    JS 要调用原生,执行的是:

    // successCallback : 成功的回调方法
    // failCallback : 失败的回调方法
    // server : 所要请求的服务名字,就是插件类的名字
    // action : 所要请求的服务具体操作,其实就是Native 的方法名,字符串。
    // actionArgs : 请求操作所带的参数,这是个数组。
    cordova.exec(successCallback, failCallback, service, action, actionArgs);

    Native 调用 JS 方法

    这个非常简单,如果是在控制器中,那么只需要像如下这样既可:

    - (void)testClick
    {
        
        NSString *jsStr = @"asyncAlert('哈哈啊哈')";
        [self.commandDelegate evalJs:jsStr];
    
    }

    这里的evalJs内部调用的其实是 UIWebView 的 stringByEvaluatingJavaScriptFromString方法。

    OK。到这里就结束了。

    demo地址: https://github.com/domanc/TestCordova.git

     
     
     
  • 相关阅读:
    Yum源的优先级
    history设置时间戳
    ntopng网络流量实时监控
    Filezilla开源FTP传输工具
    红黑树从头至尾插入和删除结点的全程演示图
    清晰理解红黑树的演变---红黑的含义
    ConcurrentHashMap的JDK1.8实现
    linux常用命令
    Java类加载过程
    MySQL存储引擎--MyISAM与InnoDB区别
  • 原文地址:https://www.cnblogs.com/dianming/p/7171259.html
Copyright © 2020-2023  润新知