博客> iOS_Cordova开发教程(二)
iOS_Cordova开发教程(二)
2018-10-19 04:22 评论:0 阅读:634 YanSY
ios Cordova web js

  上一篇文章中,简单的讲了从Cordova安装到项目创建以及简单的运行,这篇文章主要介绍的是iOS端项目实战,以及简单的将Cordova集成到自己的工程项目中的方法,以及添加Cordova自定义插件的简单使用。

  本文基于第一篇文章iOS_Cordova开发教程(一),请先阅读并按步骤走完第一篇文章中的步骤,然后再根据本文的步骤一步一步集成Cordova到已存工程项目。

1 将Cordova本地相关文件copy到已存的项目中

1.1 找到相关路径,复制文件到工程目录

  首先,进入到上一篇文章中创建的Cordova项目的路径中/Users/YanSY/Desktop/Demo/platforms/ios,找到下面需要copy的4个文件夹copy到工程项目的根路径中,

  CordovaLib  cordova  www  platform_www

如下图:

文件拷贝示意图

1.2 拷贝对应的config.xml文件到对应的工程目录

  然后将下面图中所示的config.xml文件copy到需要的iOS项目路径文件夹内,如图:

config.xml文件拷贝示意


2 配置相关参数

  2.1 打开工程,进入工程TARGETS -> Build Phases 下,然后入下图所示,点击①中的按键,创建New Run Script Phase,②为创建的Run Script:


New Run Script Phase


  2.2 将下图示意图中,①原名称Run Script修改为Copy www directory;然后讲②中的选项去掉,最后将下面的代码字段复制到③中:

NODEJS_PATH=/usr/local/bin; NVM_NODE_PATH=~/.nvm/versions/node/`nvm version 2>/dev/null`/bin; N_NODE_PATH=`find /usr/local/n/versions/node/* -maxdepth 0 -type d 2>/dev/null | tail -1`/bin; XCODE_NODE_PATH=`xcode-select --print-path`/usr/share/xcs/Node/bin; PATH=$NODEJS_PATH:$NVM_NODE_PATH:$N_NODE_PATH:$XCODE_NODE_PATH:$PATH && node cordova/lib/copy-www-build-step.js

如图:

`Copy www directory


  2.3 在工程 Build Settings -> Other Linker Flags 中添加-ObjC -all_load

Build Settings


   2.4 Add Files to ... -> CordovaLib.xcodeproj

Add Files to ... -> CordovaLib.xcodeproj


   2.5 Add Files to ... -> config.xml

Add Files to ... -> config.xml


  2.6 Add Files to ... -> www文件夹

Add Files to ... -> www文件夹


  2.7 Schemes按照下图配置,然后编译一次程序(command+R),最后导入下面两项 Build Phases -> Target Dependencies -> CordovaLib Build Phases -> Link Binary With Libraries -> libCordova.a

CordovaLib and libCordova.a


  2.8 Schemes按照下图配置,将"ViewController.h" 文件改为:

#import <Cordova>
#import <Cordova>
#import <Cordova>
@interface ViewController : CDVViewController
@end

如图:

ViewController


  至此,Cordova嵌入已存的开发项目就已经完成了,运行程序就可看到工程中wwww文件目录下,index.html文件中的网页信息了。只需要将该文件内容,改为公司需要的网页内容即可。具体交互以及自定义插件,将在后面文章中介绍。

3 自定义插件

3.1 在config.xml文件中加入下面代码:

<feature name="YourPluginName"> 
    <param name="ios-package" value="YanSYPlugin"> 
    <param name="onload" value="true"> 
</feature>

如图:

YanSYPlugin.png


3.1 创建一个YanSYPlugin类,实现下面的方法

  下面介绍一个简单的web端调用原生手机相机以及选择相册图片并返回web显示的自定义插件调用:

  • (1)YanSYPlugin.h 的实现
#import <Cordova>

@interface YanSYPlugin : CDVPlugin<UIImagePickerControllerDelegate>
{
    UIImagePickerController *_imagePickerController; // 定义相机控件类
}

// 本类插件方法 - 当在web调用时
- (void)myMethod:(CDVInvokedUrlCommand*)command;

@end
  • (2)YanSYPlugin.m 的实现
#import "YanSYPlugin.h"
//#import <GTMBase64>   // base64 转码

typedef void(^imgBlock)(NSString * data);
@interface YanSYPlugin()

@property(nonatomic,strong) imgBlock MyBlock;

@end

@implementation YanSYPlugin

- (void)myMethod:(CDVInvokedUrlCommand*)command{
    /*

     NSString* _callbackId; 回调时的id
     NSString* _className;  类名
     NSString* _methodName; 方法名
     NSArray* _arguments;   参数

     */
    [self.commandDelegate runInBackground:^{

        NSString* myarg = [command.arguments objectAtIndex:0];

        if (myarg !=nil) {
            [self switchMethodWithName:myarg andCommand:(CDVInvokedUrlCommand*)command];
        }
        else{
            return ;
        }

    }];

}

// 根据方法选择判断调用具体内容
- (void)switchMethodWithName:(NSString *)name andCommand:(CDVInvokedUrlCommand*)command{

    _imagePickerController = [[UIImagePickerController alloc] init];
    _imagePickerController.delegate = self;
    _imagePickerController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
    _imagePickerController.allowsEditing = YES;

    __block CDVPluginResult* pluginResult = nil;
    NSString * standbyJSStr = [NSString stringWithFormat:@"%@",@[removed]iVBORw0KGgoAAAANSUhEUgAAABcAAAAVCAYAAACt4nWrAAAEDWlDQ1BJQ0MgUHJvZmlsZQAAOI2NVV1oHFUUPrtzZyMkzlNsNIV0qD8NJQ2TVjShtLp/3d02bpZJNtoi6GT27s6Yyc44M7v9oU9FUHwx6psUxL+3gCAo9Q/bPrQvlQol2tQgKD60+INQ6Ium65k7M5lpurHeZe58853vnnvuuWfvBei5qliWkRQBFpquLRcy4nOHj4g9K5CEh6AXBqFXUR0rXalMAjZPC3e1W99Dwntf2dXd/p+tt0YdFSBxH2Kz5qgLiI8B8KdVy3YBevqRHz/qWh72Yui3MUDEL3q44WPXw3M+fo1pZuQs4tOIBVVTaoiXEI/MxfhGDPsxsNZfoE1q66ro5aJim3XdoLFw72H+n23BaIXzbcOnz5mfPoTvYVz7KzUl5+FRxEuqkp9G/Ajia219thzg25abkRE/BpDc3pqvphHvRFys2weqvp+krbWKIX7nhDbzLOItiM8358pTwdirqpPFnMF2xLc1WvLyOwTAibpbmvHHcvttU57y5+XqNZrLe3lE/Pq8eUj2fXKfOe3pfOjzhJYtB/yll5SDFcSDiH+hRkH25+L+sdxKEAMZahrlSX8ukqMOWy/jXW2m6M9LDBc31B9LFuv6gVKg/0Szi3KAr1kGq1GMjU/aLbnq6/lRxc4XfJ98hTargX++DbMJBSiYMIe9Ck1YAxFkKEAG3xbYaKmDDgYyFK0UGYpfoWYXG+fAPPI6tJnNwb7ClP7IyF+D+bjOtCpkhz6CFrIa/I6sFtNl8auFXGMTP34sNwI/JhkgEtmDz14ySfaRcTIBInmKPE32kxyyE2Tv+thKbEVePDfW/byMM1Kmm0XdObS7oGD/MypMXFPXrCwOtoYjyyn7BV29/MZfsVzpLDdRtuIZnbpXzvlf+ev8MvYr/Gqk4H/kV/G3csdazLuyTMPsbFhzd1UabQbjFvDRmcWJxR3zcfHkVw9GfpbJmeev9F08WW8uDkaslwX6avlWGU6NRKz0g/SHtCy9J30o/ca9zX3Kfc19zn3BXQKRO8ud477hLnAfc1/G9mrzGlrfexZ5GLdn6ZZrrEohI2wVHhZywjbhUWEy8icMCGNCUdiBlq3r+xafL549HQ5jH+an+1y+LlYBifuxAvRN/lVVVOlwlCkdVm9NOL5BE4wkQ2SMlDZU97hX86EilU/lUmkQUztTE6mx1EEPh7OmdqBtAvv8HdWpbrJS6tJj3n0CWdM6busNzRV3S9KTYhqvNiqWmuroiKgYhshMjmhTh9ptWhsF7970j/SbMrsPE1suR5z7DMC+P/Hs+y7ijrQAlhyAgccjbhjPygfeBTjzhNqy28EdkUh8C+DU9+z2v/oyeH791OncxHOs5y2AtTc7nb/f73TWPkD/qwBnjX8BoJ98VVBg/m8AAAEFSURBVDgRY/z969//GO9HDAd3f2agNmDKjX9KE4NBDmXasPwDTgcX14sxPP+vg4JBYsQCJmIVkqNu1HCsoUbTYGEJiBBgCE8SZLCw5WTg4CDeLkt7bgYrB24UFx878JXh+MGvcDGW6ctl4BxSGCCDSxpQk2VPwysUw4l3Kik2Q9XS1HAWkCV//vxn2LL2M8Od6z9Q3AfyOnq4oiggwGF5++YvQ4TzA4Yrl75jUSpGkeFMM3re4DAYi10kCjHt3kb9ohbmBqZHN3/B2FSnmdg4GaluKMxAJitn1FwGk6AGzZRXKcrAykId16Obw2RgwsmwYJMcg4omBwOlVniH8jFISbPBPQ0Ay3NHXHSKRhIAAAAASUVORK5CYII="];

    if ([name isEqualToString:@"调用相机"]) {

        [self selectImageFromCameraWithBlock:^(NSString *data) {
            // 因当前转码格式为iOS原生转码,web端无法解析 ,所以百度了一波图片转码成功后复用,若转码格式正确 可直接上传字符串
            // NSString *jsStr = [NSString stringWithFormat:@[removed]%@",data];
            // 使用备用字符串上传
            pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:standbyJSStr];
            [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
        }];
    }
    else if ([name isEqualToString:@"查看相册"]){
        [self selectImageFromAlbumWithBlock:^(NSString *data) {
            // 因当前转码格式为iOS原生转码,web端无法解析 ,所以百度了一波图片转码成功后复用,若转码格式正确 可直接上传字符串
            // NSString *jsStr = [NSString stringWithFormat:@[removed]%@",data];
            // 使用备用字符串上传
            pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:standbyJSStr];
            [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
        }];
    }
    else{
        pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"You Are Error"];
        [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
    }
}

#pragma mark 从摄像头获取图片或视频
- (void)selectImageFromCameraWithBlock:(imgBlock)block{

    self.MyBlock = block;
    _imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
    //相机类型(拍照、录像...)字符串需要做相应的类型转换
    //视频上传质量
    //UIImagePickerControllerQualityTypeHigh高清
    //UIImagePickerControllerQualityTypeMedium中等质量
    //UIImagePickerControllerQualityTypeLow低质量
    //UIImagePickerControllerQualityType640x480
    _imagePickerController.videoQuality = UIImagePickerControllerQualityTypeHigh;
    //设置摄像头模式(拍照,录制视频)为录像模式
    _imagePickerController.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto;
    [self.viewController presentViewController:_imagePickerController animated:YES completion:nil];
}

#pragma mark 从相册获取图片或视频
- (void)selectImageFromAlbumWithBlock:(imgBlock)block{
    self.MyBlock = block;
    _imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
    [self.viewController presentViewController:_imagePickerController animated:YES completion:nil];
}

#pragma mark UIImagePickerControllerDelegate
//该代理方法仅适用于只选取图片时
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)image editingInfo:(nullable NSDictionary<NSString> *)editingInfo {

    NSString *encodedImageStr = [self imageProcessing:image];
    self.MyBlock(encodedImageStr);
}

//适用获取所有媒体资源,只需判断资源类型
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString> *)info{

    NSString *encodedImageStr = [self imageProcessing:info[UIImagePickerControllerEditedImage]];
    self.MyBlock(encodedImageStr);
    [self.viewController dismissViewControllerAnimated:YES completion:nil];
}

// 图像处理 若未下载base64者 可不用查看
- (NSString *)imageProcessing:(UIImage *)proImage{

    // 判断传过来照片的大小进行裁剪
    CGFloat width  = proImage.size.width;
    CGFloat height = proImage.size.height;
    CGSize size;
    if (width>height) {
        size = CGSizeMake(800, 450);
    }
    else{
        size = CGSizeMake(450, 800);
    }
    // 创建一个bitmap的context
    // 并把它设置成为当前正在使用的context
    UIGraphicsBeginImageContext(size);
    // 绘制改变大小的图片
    [proImage drawInRect:CGRectMake(0,0, size.width, size.height)];
    // 从当前context中创建一个改变大小后的图片
    UIImage * tailoringImage =UIGraphicsGetImageFromCurrentImageContext();
    // 使当前的context出堆栈
    UIGraphicsEndImageContext();

    // 判断图片大小进行压缩
    NSData *imageData = UIImageJPEGRepresentation(tailoringImage,1.0);

    NSLog(@"imagedata == %lud,size.width = %f==%f",(unsigned long)imageData.length,tailoringImage.size.width,tailoringImage.size.height);

    if (imageData.length>100*1024) {
        if (imageData.length>1024*1024) {     //1M以及以上
            imageData=UIImageJPEGRepresentation(tailoringImage, 0.1);
        }else if (imageData.length>512*1024) {//0.5M-1M
            imageData=UIImageJPEGRepresentation(tailoringImage, 0.3);
        }else if (imageData.length>200*1024) {//0.25M-0.5M
            imageData=UIImageJPEGRepresentation(tailoringImage, 0.7);
        }
    }
    NSLog(@"imagedata == %lud,size.width = %f==%f",(unsigned long)imageData.length,tailoringImage.size.width,tailoringImage.size.height);

    // 最后进行 base64 转码
    // 注:iOS端转base64 的方法可能web无法简析为图片,可从pod下载第三方库 GTMBase64 进行转码 ,这里不再赘述
    // NSString * encodedImageStr = [GTMBase64 stringByEncoding[removed] yourCallbackFunction, false);

            function cameraBTClick(){
                Cordova.exec&#40;successFunction, failFunction, "YanSYPlugin", "myMethod", ["调用相机"]&#41;;
            }
        function PhotoAlbumBTClick(){
            Cordova.exec&#40;failFunction, failFunction, "YanSYPlugin", "myMethod", ["查看相册"]&#41;;
        }

        function failFunction(error){
            alert&#40;"error"&#41;;
            document.getElementById("returnValue").value = img;
        }
        function aaaa(){
            document.getElementById("2")[removed] = "<img>

    </>

    <>
        <>点击下面按钮调用相机拍照</>
        < onclick>调用相机&lt;/button&gt;
    &lt;/body&gt;

    &lt;body&gt;
        <p>点击下面按钮选择相册照片</p>
        &lt;button onclick="PhotoAlbumBTClick()"&gt;查看相册&lt;/button&gt;
        &lt;button onclick="aaaa()"&gt;测试&lt;/button&gt;
        <h1>这是回调结果展示区</h1>
        &lt;textarea id ="returnValue" type="value" rows="5" cols="40"&gt;
        &lt;/textarea&gt;

    &lt;/body&gt;

    &lt;body&gt;/Users/YanSY/Desktop/代码运行示意11.gif
        <p>
        <img id="1">
        </p>
        <p id="2"> </p>

    &lt;/body&gt;

&lt;/html&gt;

  将以上代码,按步骤写入程序中,可测试调用原生相机,注意,需要在plist文件中添加隐私权限。运行效果示例如下,因为转码格式为iOS原生格式转码,与web不兼容,所以上传回调时并未用选择照片或者拍摄照片上传,如果需要,请在工程中下载第三方库 GTMBase64 进行转码回调。

代码运行示意.gif


  下面附上自己gitHub代码段,如果有需要,请下载查看Cordova测试代码程序示意,如果觉得文章对你有所帮助,麻烦点一个❤️,谢谢。

收藏
0
sina weixin mail 回到顶部