cocos2dx-lua在ios上实现生成及扫描二维码

来源:互联网 发布:万网域名申请流程 编辑:程序博客网 时间:2024/05/19 05:02

首先说明下,我是支持用ios原生方法实现的。不过扫描二维码原生方法不支持ios7.0之前的设备,所以生成二维码用的原生方法实现,而扫描二维码用zBar sdk实现的(当然也可以用google官方的zXing sdk)。其中zBar中包含生成二维码的方法,而且更多样,我只是喜欢尽量用原生方法来实现。

这里我把所有生成二维码的代码和lua调用的扫描二维码方法都放在了项目->frameworks->runtime-src->proj.ios_mac->ios->AppController.h和AppController.mm中

zBar sdk及相关类放到了 项目->frameworks->runtime-src->proj.ios_mac->ios下。

-----1.原生生成二维码

------------1.1AppController.h中添加代码:

//生成二维码+(CIImage *) creatQRcodeWithUrlstring:(NSString *)urlString;//改变图片大小 (正方形图片)+ (UIImage *)changeImageSizeWithCIImage:(CIImage *)ciImage andSize:(CGFloat)size;//保存(暂时没用)+(BOOL)writeImage:(UIImage*)image toFileAtPath:(NSString*)aPath;//生成二维码+(void)createQRCode:(NSDictionary *)info;
------------1.2AppController.mm中添加代码:
/** *  根据字符串生成二维码 CIImage 对象 * *  @param urlString 需要生成二维码的字符串 * *  @return 生成的二维码 */+ (CIImage *)creatQRcodeWithUrlstring:(NSString *)urlString{    // 1.实例化二维码滤镜    CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];    // 2.恢复滤镜的默认属性 (因为滤镜有可能保存上一次的属性)    [filter setDefaults];    // 3.将字符串转换成NSdata    NSData *data  = [urlString dataUsingEncoding:NSUTF8StringEncoding];    // 4.通过KVO设置滤镜, 传入data, 将来滤镜就知道要通过传入的数据生成二维码    [filter setValue:data forKey:@"inputMessage"];    // 5.生成二维码    CIImage *outputImage = [filter outputImage];    return outputImage;}/** *  改变图片大小 (正方形图片) * *  @param ciImage 需要改变大小的CIImage 对象的图片 *  @param size    图片大小 (正方形图片 只需要一个数) * *  @return 生成的目标图片 */+ (UIImage *)changeImageSizeWithCIImage:(CIImage *)ciImage andSize:(CGFloat)size{    CGRect extent = CGRectIntegral(ciImage.extent);    CGFloat scale = MIN(size/CGRectGetWidth(extent), size/CGRectGetHeight(extent));        // 创建bitmap;    size_t width = CGRectGetWidth(extent) * scale;    size_t height = CGRectGetHeight(extent) * scale;    CGColorSpaceRef cs = CGColorSpaceCreateDeviceGray();    CGContextRef bitmapRef = CGBitmapContextCreate(nil, width, height, 8, 0, cs, (CGBitmapInfo)kCGImageAlphaNone);    CIContext *context = [CIContext contextWithOptions:nil];    CGImageRef bitmapImage = [context createCGImage:ciImage fromRect:extent];    CGContextSetInterpolationQuality(bitmapRef, kCGInterpolationNone);    CGContextScaleCTM(bitmapRef, scale, scale);    CGContextDrawImage(bitmapRef, extent, bitmapImage);        // 保存bitmap到图片    CGImageRef scaledImage = CGBitmapContextCreateImage(bitmapRef);    CGContextRelease(bitmapRef);    CGImageRelease(bitmapImage);        return [UIImage imageWithCGImage:scaledImage];}+ (BOOL)writeImage:(UIImage*)image toFileAtPath:(NSString*)aPath{    if ((image == nil) || (aPath == nil) || ([aPath isEqualToString:@""]))        return NO;    @try    {        NSData *imageData = nil;        NSString *ext = [aPath pathExtension];        if ([ext isEqualToString:@"png"])        {            imageData = UIImagePNGRepresentation(image);        }        else        {            // the rest, we write to jpeg            // 0. best, 1. lost. about compress.            imageData = UIImageJPEGRepresentation(image, 0);        }        if ((imageData == nil) || ([imageData length] <= 0))            return NO;        [imageData writeToFile:aPath atomically:YES];        return YES;    }    @catch (NSException *e)    {        NSLog(@"create thumbnail exception.");    }    return NO;}/* * 项目-TARGETS-fightGame-mobile-Build Phases-Link Binary With Libraries添加CoreImage.framework */+(void) createQRCode:(NSDictionary *)info{    int _callBack = [[info objectForKey:@"listener"] intValue];    NSString *qrCodeStr = [info objectForKey:@"qrCodeStr"];        CIImage *ciImage = [self creatQRcodeWithUrlstring:qrCodeStr];    UIImage *uiImage = [self changeImageSizeWithCIImage:ciImage andSize:180];    NSData *imageData = UIImagePNGRepresentation(uiImage);        std::string path = cocos2d::FileUtils::getInstance()->getWritablePath() + "qrCode.png";    const char* pathC = path.c_str();    NSString * pathN = [NSString stringWithUTF8String:pathC];    bool isSuccess = [imageData writeToFile:pathN atomically:YES];        cocos2d::LuaBridge::pushLuaFunctionById(_callBack);    cocos2d::LuaValueDict dict;    dict["isSuccess"] =cocos2d::LuaValue::booleanValue(isSuccess);    cocos2d::LuaBridge::getStack()->pushLuaValueDict( dict );    cocos2d::LuaBridge::getStack()->executeFunction(1);    cocos2d::LuaBridge::releaseLuaFunctionById(_callBack);}

其中createQRcode方法为最终lua掉用oc的方法,将生成的图片存到cocos2dx的writablePath下,并保存为"qrCode.png"。最后在lua端取出用sprite显示

------------1.3lua调用createQRcode方法,并显示

        local callBack = function (message)            local filePath = cc.FileUtils:getInstance():getWritablePath()            filePath = filePath.."qrCode.png"            local rect = cc.rect(0, 0, 180, 180)            local sprite = cc.Sprite:create()             sprite:initWithFile(filePath, rect)            sprite:setPosition(300, 300)            self:addChild(sprite)        end        local info = {listener = callBack, qrCodeStr = "https://www.baidu.com/"}        luaoc.callStaticMethod("AppController", "createQRCode", info)
------------1.4添加CoreImage.framework依赖框架(二维码扫描需要用到)

项目->TARGETS->Build Phases->Link Binary With Libraries->左下角“+”号,search框中输入CoreImage.framework,选择匹配的选项即可。
-----2.zBar sdk实现二维码扫描

------------2.1下载zBar sdk 
地址在后面给出。

------------2.2将zBarSDK解压并将解压后的zBarSDK导入到工程项目->frameworks->runtime-src->proj.ios_mac->ios下。

解压后的zBarSDK目录包含:Headers,libzbar.a,Resources。

如果导入工程后没有自动添加libzbar.a依赖框架,则需要手动添加该依赖框架(如1.4)

------------2.3项目->frameworks->runtime-src->proj.ios_mac->ios->zBarSDK下新建ZCZBarViewController.h和ZCZBarViewController.mm两个文件,并导入工程,代码如下。
------------2.4ZCZBarViewController.h代码:

/* 版本说明 iOS研究院 305044955 1.8版本 剔除生成二维码文件,使用iOS7原生生成二维码 1.7版本 修复了开启相机点击,用户如果点击拒绝,会导致崩溃的问题 1.6版本 增加了支持了区别条码和二维码,可以关闭扫描二维码来增加条码扫描速度 1.5版本 修正了iOS6下扫描会卡死,增加了iOS7下支持条形码,修改了算法,增加了效率 1.4版本 支持iOS8系统,修改了相应UI的适配问题 1.3版本 全新支持arm7s arm64 全新支持ARC 1.2版本 ZC封装的ZBar二维码SDK    1、更新类名从CustomViewController更改为ZCZBarViewController    2、删除掉代理的相关代码 1.1版本 ZC封装的ZBar二维码SDK~    1、增加block回调    2、取消代理    3、增加适配IOS7(ios7在AVFoundation中增加了扫描二维码功能) 1.0版本 ZC封装的ZBar二维码SDK~1.0版本初始建立  二维码编译顺序 Zbar编译 需要添加AVFoundation  CoreMedia  CoreVideo QuartzCore libiconv  //示例代码扫描代码BOOL代表是否关闭二维码扫描,专门扫描条形码 ZCZBarViewController*vc=[[ZCZBarViewController alloc]initWithIsQRCode:NO Block:^(NSString *result, BOOL isFinish) { if (isFinish) { NSLog(@"最后的结果%@",result); }  }];  [self presentViewController:vc animated:YES completion:nil];  生成二维码 [ZCZBarViewController createImageWithImageView:imageView String:@"http://www.baidu.com"Scale:4]; */#import <UIKit/UIKit.h>#import <AVFoundation/AVFoundation.h>#import "ZBarReaderController.h"#import <CoreImage/CoreImage.h>#define IOS7 [[[UIDevice currentDevice] systemVersion]floatValue]>=7@interface ZCZBarViewController : UIViewController<AVCaptureVideoDataOutputSampleBufferDelegate, UINavigationControllerDelegate, UIImagePickerControllerDelegate,ZBarReaderDelegate,AVCaptureMetadataOutputObjectsDelegate>{    int num;    BOOL upOrdown;    NSTimer * timer;    UIImageView*_line;}@property (nonatomic,strong) AVCaptureVideoPreviewLayer *captureVideoPreviewLayer;@property (nonatomic, strong) AVCaptureSession *captureSession;@property (nonatomic, assign) BOOL isScanning;@property (nonatomic,copy)void(^ScanResult)(NSString*result,BOOL isSucceed);@property (nonatomic)BOOL isQRCode;//初始化函数-(id)initWithIsQRCode:(BOOL)isQRCode Block:(void(^)(NSString*,BOOL))a;//正则表达式对扫描结果筛选+(NSString*)zhengze:(NSString*)str;//创建二维码+(void)createImageWithImageView:(UIImageView*)imageView String:(NSString*)str Scale:(CGFloat)scale;@end
------------2.4ZCZBarViewController.mm代码:
#import "ZCZBarViewController.h"#import <AssetsLibrary/AssetsLibrary.h>@interface ZCZBarViewController ()@end#define WIDTH ( ([UIScreen mainScreen].bounds.size.width>[UIScreen mainScreen].bounds.size.height)?[UIScreen mainScreen].bounds.size.width:[UIScreen mainScreen].bounds.size.height )//[UIScreen mainScreen].bounds.size.width#define HEIGHT ( ([UIScreen mainScreen].bounds.size.width<[UIScreen mainScreen].bounds.size.height)?[UIScreen mainScreen].bounds.size.width:[UIScreen mainScreen].bounds.size.height )//[UIScreen mainScreen].bounds.size.height@implementation ZCZBarViewController- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil{    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];    if (self) {        // Custom initialization    }    return self;}-(id)initWithIsQRCode:(BOOL)isQRCode Block:(void(^)(NSString*,BOOL))a{    if (self=[super init]) {        self.ScanResult=a;        self.isQRCode=isQRCode;            }        return self;}-(void)createView{    //qrcode_scan_bg_Green_iphone5@2x.png  qrcode_scan_bg_Green@2x.png    UIImage*image= [UIImage imageNamed:@"qrcode_scan_bg_Green@2x.png"];    float capWidth=image.size.width/2;    float capHeight=image.size.height/2;        image=[image stretchableImageWithLeftCapWidth:capWidth topCapHeight:capHeight];    UIImageView* bgImageView=[[UIImageView alloc]initWithFrame:CGRectMake(0, 64, WIDTH, HEIGHT-64)];    //bgImageView.contentMode=UIViewContentModeTop;    bgImageView.clipsToBounds=YES;    bgImageView.image=image;    bgImageView.userInteractionEnabled=YES;    [self.view addSubview:bgImageView];    //    UILabel * label = [[UILabel alloc] initWithFrame:CGRectMake(0, bgImageView.frame.size.height-140, WIDTH, 40)];//    label.text = @"将取景框对准二维码,即可自动扫描。";//    label.textColor = [UIColor whiteColor];//    label.textAlignment = NSTextAlignmentCenter;//    label.lineBreakMode = NSLineBreakByWordWrapping;//    label.numberOfLines = 2;//    label.font=[UIFont systemFontOfSize:12];//    label.backgroundColor = [UIColor clearColor];//    [bgImageView addSubview:label];                _line = [[UIImageView alloc] initWithFrame:CGRectMake((WIDTH-220)/2, 70, 220, 2)];    _line.image = [UIImage imageNamed:@"qrcode_scan_light_green.png"];    [bgImageView addSubview:_line];       //  //下方相册//    UIImageView*scanImageView=[[UIImageView alloc]initWithFrame:CGRectMake(0, HEIGHT-100, WIDTH, 100)];//    scanImageView.image=[UIImage imageNamed:@"qrcode_scan_bar.png"];//    scanImageView.userInteractionEnabled=YES;//    [self.view addSubview:scanImageView];//    NSArray*unSelectImageNames=@[@"qrcode_scan_btn_photo_nor.png",@"qrcode_scan_btn_flash_nor.png",@"qrcode_scan_btn_myqrcode_nor.png"];//    NSArray*selectImageNames=@[@"qrcode_scan_btn_photo_down.png",@"qrcode_scan_btn_flash_down.png",@"qrcode_scan_btn_myqrcode_down.png"];//    //    for (int i=0; i<unSelectImageNames.count; i++) {//        UIButton*button=[UIButton buttonWithType:UIButtonTypeCustom];//        [button setImage:[UIImage imageNamed:unSelectImageNames[i]] forState:UIControlStateNormal];//        [button setImage:[UIImage imageNamed:selectImageNames[i]] forState:UIControlStateHighlighted];//        button.frame=CGRectMake(WIDTH/3*i, 0, WIDTH/3, 100);//        [scanImageView addSubview:button];//        if (i==0) {//            [button addTarget:self action:@selector(pressPhotoLibraryButton:) forControlEvents:UIControlEventTouchUpInside];//        }//        if (i==1) {//            [button addTarget:self action:@selector(flashLightClick) forControlEvents:UIControlEventTouchUpInside];//        }//        if (i==2) {//            button.hidden=YES;//        }//        //    }            //假导航//    UIImageView*navImageView=[[UIImageView alloc]initWithFrame:CGRectMake(0, 0, WIDTH, 64)];//    navImageView.image=[UIImage imageNamed:@"qrcode_scan_bar.png"];//    navImageView.userInteractionEnabled=YES;//    [self.view addSubview:navImageView];        UILabel*titleLabel=[[UILabel alloc]initWithFrame:CGRectMake(WIDTH/2-32, 20, 64, 44)];    titleLabel.textColor=[UIColor whiteColor];    titleLabel.backgroundColor = [UIColor clearColor];    titleLabel.text=@"扫一扫";    [self.view addSubview:titleLabel];//    [navImageView addSubview:titleLabel];              UIButton*button = [UIButton buttonWithType:UIButtonTypeCustom];    [button setImage:[UIImage imageNamed:@"qrcode_scan_titlebar_back_pressed@2x.png"] forState:UIControlStateHighlighted];    [button setImage:[UIImage imageNamed:@"qrcode_scan_titlebar_back_nor.png"] forState:UIControlStateNormal];        [button setFrame:CGRectMake(10,10, 48, 48)];    [button addTarget:self action:@selector(pressCancelButton:) forControlEvents:UIControlEventTouchUpInside];    [self.view addSubview:button];   timer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(animation1) userInfo:nil repeats:YES];}-(void)animation1{    [UIView animateWithDuration:2 animations:^{                 _line.frame = CGRectMake((WIDTH-220)/2, 70+HEIGHT-310, 220, 2);    }completion:^(BOOL finished) {        [UIView animateWithDuration:2 animations:^{          _line.frame = CGRectMake((WIDTH-220)/2, 70, 220, 2);        }];        }];    }//开启关闭闪光灯-(void)flashLightClick{    AVCaptureDevice * device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];        if (device.torchMode==AVCaptureTorchModeOff) {        //闪光灯开启        [device lockForConfiguration:nil];        [device setTorchMode:AVCaptureTorchModeOn];            }else {        //闪光灯关闭                [device setTorchMode:AVCaptureTorchModeOff];    }}- (void)viewDidLoad{      //相机界面的定制在self.view上加载即可    BOOL Custom= [UIImagePickerController                  isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera];//判断摄像头是否能用    if (Custom) {        [self initCapture];//启动摄像头    }else{        self.view.backgroundColor=[UIColor whiteColor];    }    [super viewDidLoad];    [self createView];        }#pragma mark 选择相册- (void)pressPhotoLibraryButton:(UIButton *)button{  if (timer) {    [timer invalidate];    timer=nil;}    _line.frame = CGRectMake((WIDTH-220)/2, 70, 220, 2);    num = 0;    upOrdown = NO;            UIImagePickerController *picker = [[UIImagePickerController alloc] init];    picker.allowsEditing = YES;    picker.delegate = self;    picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;    [self presentViewController:picker animated:YES completion:^{        self.isScanning = NO;        [self.captureSession stopRunning];    }];}#pragma mark 点击取消- (void)pressCancelButton:(UIButton *)button{    self.isScanning = NO;    [self.captureSession stopRunning];        self.ScanResult(nil,NO);    if (timer) {        [timer invalidate];        timer=nil;    }    _line.frame = CGRectMake((WIDTH-220)/2, 70, 220, 2);    num = 0;    upOrdown = NO;    [self dismissViewControllerAnimated:YES completion:nil];}#pragma mark 开启相机- (void)initCapture{    //ios6上也没有“设置--隐私--相机” 那一项    if (IOS7) {        NSString *mediaType = AVMediaTypeVideo;        AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:mediaType];                if(authStatus == AVAuthorizationStatusRestricted || authStatus == AVAuthorizationStatusDenied){            NSString*str=[NSString stringWithFormat:@"请在系统设置-%@-相机中打开允许使用相机",  [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]];            UIAlertView *alert=[[UIAlertView alloc]initWithTitle:@"提示" message:str delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];            [alert show];            return;        }    }        self.captureSession = [[AVCaptureSession alloc] init];        AVCaptureDevice* inputDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];        AVCaptureDeviceInput *captureInput = [AVCaptureDeviceInput deviceInputWithDevice:inputDevice error:nil];    [self.captureSession addInput:captureInput];        AVCaptureVideoDataOutput *captureOutput = [[AVCaptureVideoDataOutput alloc] init];    captureOutput.alwaysDiscardsLateVideoFrames = YES;            if (IOS7) {        AVCaptureMetadataOutput*_output=[[AVCaptureMetadataOutput alloc]init];        [_output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];        [self.captureSession setSessionPreset:AVCaptureSessionPresetHigh];        [self.captureSession addOutput:_output];        //在这里修改了,可以让原生兼容二维码和条形码,无需在使用Zbar                if (_isQRCode) {            _output.metadataObjectTypes =@[AVMetadataObjectTypeQRCode];                   }else{             _output.metadataObjectTypes =@[AVMetadataObjectTypeEAN13Code,AVMetadataObjectTypeEAN8Code,AVMetadataObjectTypeCode128Code,AVMetadataObjectTypeQRCode];        }                       if (!self.captureVideoPreviewLayer) {            self.captureVideoPreviewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.captureSession];        }        // NSLog(@"prev %p %@", self.prevLayer, self.prevLayer);        self.captureVideoPreviewLayer.frame = CGRectMake(0, 0, WIDTH, HEIGHT);//self.view.bounds;        self.captureVideoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;        [self.view.layer addSublayer: self.captureVideoPreviewLayer];                self.isScanning = YES;        [self.captureSession startRunning];                    }else{        dispatch_queue_t queue = dispatch_queue_create("myQueue", NULL);        [captureOutput setSampleBufferDelegate:self queue:queue];                NSString* key = (NSString *)kCVPixelBufferPixelFormatTypeKey;        NSNumber* value = [NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA];        NSDictionary *videoSettings = [NSDictionary dictionaryWithObject:value forKey:key];        [captureOutput setVideoSettings:videoSettings];        [self.captureSession addOutput:captureOutput];                NSString* preset = 0;        if (NSClassFromString(@"NSOrderedSet") && // Proxy for "is this iOS 5" ...            [UIScreen mainScreen].scale > 1 &&            [inputDevice             supportsAVCaptureSessionPreset:AVCaptureSessionPresetiFrame960x540]) {                // NSLog(@"960");                preset = AVCaptureSessionPresetiFrame960x540;            }        if (!preset) {            // NSLog(@"MED");            preset = AVCaptureSessionPresetMedium;        }        self.captureSession.sessionPreset = preset;                if (!self.captureVideoPreviewLayer) {            self.captureVideoPreviewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.captureSession];        }        // NSLog(@"prev %p %@", self.prevLayer, self.prevLayer);        self.captureVideoPreviewLayer.frame = CGRectMake(0, 0, WIDTH, HEIGHT);//self.view.bounds;        self.captureVideoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;        [self.view.layer addSublayer: self.captureVideoPreviewLayer];                self.isScanning = YES;        [self.captureSession startRunning];                    }        }- (UIImage *) imageFromSampleBuffer:(CMSampleBufferRef) sampleBuffer{    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);    // Lock the base address of the pixel buffer    CVPixelBufferLockBaseAddress(imageBuffer,0);        // Get the number of bytes per row for the pixel buffer    size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);    // Get the pixel buffer width and height    size_t width = CVPixelBufferGetWidth(imageBuffer);    size_t height = CVPixelBufferGetHeight(imageBuffer);        // Create a device-dependent RGB color space    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();    if (!colorSpace)    {        NSLog(@"CGColorSpaceCreateDeviceRGB failure");        return nil;    }        // Get the base address of the pixel buffer    void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer);    // Get the data size for contiguous planes of the pixel buffer.    size_t bufferSize = CVPixelBufferGetDataSize(imageBuffer);        // Create a Quartz direct-access data provider that uses data we supply    CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, baseAddress, bufferSize,                                                              NULL);    // Create a bitmap image from data supplied by our data provider    CGImageRef cgImage =    CGImageCreate(width,                  height,                  8,                  32,                  bytesPerRow,                  colorSpace,                  kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Little,                  provider,                  NULL,                  true,                  kCGRenderingIntentDefault);    CGDataProviderRelease(provider);    CGColorSpaceRelease(colorSpace);        // Create and return an image object representing the specified Quartz image    UIImage *image = [UIImage imageWithCGImage:cgImage];        return image;}#pragma mark 对图像进行解码- (void)decodeImage:(UIImage *)image{        self.isScanning = NO;    ZBarSymbol *symbol = nil;        ZBarReaderController* read = [ZBarReaderController new];        read.readerDelegate = self;        CGImageRef cgImageRef = image.CGImage;        for(symbol in [read scanImage:cgImageRef])break;        if (symbol!=nil) {        if (timer) {            [timer invalidate];            timer=nil;        }                _line.frame = CGRectMake((WIDTH-220)/2, 70, 220, 2);        num = 0;        upOrdown = NO;        self.ScanResult(symbol.data,YES);        [self.captureSession stopRunning];        [self dismissViewControllerAnimated:YES completion:nil];    }else{        timer = [NSTimer scheduledTimerWithTimeInterval:.02 target:self selector:@selector(animation1) userInfo:nil repeats:YES];        num = 0;        upOrdown = NO;        self.isScanning = YES;        [self.captureSession startRunning];    }            }#pragma mark - AVCaptureVideoDataOutputSampleBufferDelegate- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection{        UIImage *image = [self imageFromSampleBuffer:sampleBuffer];        [self decodeImage:image];}#pragma mark AVCaptureMetadataOutputObjectsDelegate//IOS7下触发- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection{            if (metadataObjects.count>0)    {        AVMetadataMachineReadableCodeObject * metadataObject = [metadataObjects objectAtIndex:0];        self.ScanResult(metadataObject.stringValue,YES);    }        [self.captureSession stopRunning];    _line.frame = CGRectMake((WIDTH-220)/2, 70, 220, 2);    num = 0;    upOrdown = NO;    [self dismissViewControllerAnimated:YES completion:nil];        }#pragma mark - UIImagePickerControllerDelegate- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{    if (timer) {        [timer invalidate];        timer=nil;    }    _line.frame = CGRectMake((WIDTH-220)/2, 70, 220, 2);    num = 0;    upOrdown = NO;    UIImage *image = [info objectForKey:@"UIImagePickerControllerEditedImage"];    [self dismissViewControllerAnimated:YES completion:^{[self decodeImage:image];}];        }- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker{    if (timer) {        [timer invalidate];        timer=nil;    }    _line.frame = CGRectMake((WIDTH-220)/2, 70, 220, 2);    num = 0;    upOrdown = NO;    timer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(animation1) userInfo:nil repeats:YES];    [self dismissViewControllerAnimated:YES completion:^{        self.isScanning = YES;        [self.captureSession startRunning];    }];}#pragma mark - DecoderDelegate+(NSString*)zhengze:(NSString*)str{        NSError *error;    //http+:[^\\s]* 这是检测网址的正则表达式    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"http+:[^\\s]*" options:0 error:&error];//筛选        if (regex != nil) {        NSTextCheckingResult *firstMatch = [regex firstMatchInString:str options:0 range:NSMakeRange(0, [str length])];                if (firstMatch) {            NSRange resultRange = [firstMatch rangeAtIndex:0];            //从urlString中截取数据            NSString *result1 = [str substringWithRange:resultRange];            NSLog(@"正则表达后的结果%@",result1);            return result1;                    }    }    return nil;}+(void)createImageWithImageView:(UIImageView*)imageView String:(NSString*)str Scale:(CGFloat)scale{    CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];    [filter setDefaults];        NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];    [filter setValue:data forKey:@"inputMessage"];        CIImage *outputImage = [filter outputImage];        CIContext *context = [CIContext contextWithOptions:nil];    CGImageRef cgImage = [context createCGImage:outputImage                                       fromRect:[outputImage extent]];        UIImage *image = [UIImage imageWithCGImage:cgImage                                         scale:1.0                                   orientation:UIImageOrientationUp];        UIImage *resized = nil;    CGFloat width = image.size.width*scale;    CGFloat height = image.size.height*scale;        UIGraphicsBeginImageContext(CGSizeMake(width, height));    CGContextRef context1 = UIGraphicsGetCurrentContext();    CGContextSetInterpolationQuality(context1, kCGInterpolationNone);    [image drawInRect:CGRectMake(0, -50, width, height)];    resized = UIGraphicsGetImageFromCurrentImageContext();    UIGraphicsEndImageContext();    imageView.image = resized;    CGImageRelease(cgImage);}- (void)didReceiveMemoryWarning{    [super didReceiveMemoryWarning];    // Dispose of any resources that can be recreated.}/*#pragma mark - Navigation// In a storyboard-based application, you will often want to do a little preparation before navigation- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{    // Get the new view controller using [segue destinationViewController].    // Pass the selected object to the new view controller.}*/////支持旋转//-(BOOL)shouldAutorotate{//    return NO;//}////支持的方向//- (UIInterfaceOrientationMask)supportedInterfaceOrientations {//    return UIInterfaceOrientationMaskPortrait;//}@end

------------2.5AppController.h中添加代码:

//获取当前正在显示的ViewController+ (UIViewController *)getCurrentVC;//获取当前屏幕中present出来的viewcontroller。- (UIViewController *)getPresentedViewController;//扫描二维码+(void)scanQRCode:(NSDictionary *)info;
------------2.5AppController.mm中添加代码:
//获取当前正在显示的ViewController+ (UIViewController *)getCurrentVC{    UIViewController *result = nil;        UIWindow * window = [[UIApplication sharedApplication] keyWindow];    if (window.windowLevel != UIWindowLevelNormal)    {        NSArray *windows = [[UIApplication sharedApplication] windows];        for(UIWindow * tmpWin in windows)        {            if (tmpWin.windowLevel == UIWindowLevelNormal)            {                window = tmpWin;                break;            }        }    }    UIView *frontView = [[window subviews] objectAtIndex:0];    id nextResponder = [frontView nextResponder];        if ([nextResponder isKindOfClass:[UIViewController class]])        result = nextResponder;    else        result = window.rootViewController;        return result;}//获取当前屏幕中present出来的viewcontroller。- (UIViewController *)getPresentedViewController{    UIViewController *appRootVC = [UIApplication sharedApplication].keyWindow.rootViewController;    UIViewController *topVC = appRootVC;    if (topVC.presentedViewController) {        topVC = topVC.presentedViewController;    }        return topVC;}+(void) scanQRCode:(NSDictionary *)info{    int _callBack = [[info objectForKey:@"listener"] intValue];    //    SGScanningQRCodeVC *scanningQRCodeVC = [[SGScanningQRCodeVC alloc] init];//    [scanningQRCodeVC setupScanningQRCode];        UIViewController *nowViewController = [self getCurrentVC];        ZCZBarViewController*vc=[[ZCZBarViewController alloc]initWithIsQRCode:NO Block:^(NSString *result, BOOL isFinish) {        if (isFinish) {            NSLog(@"最后的结果%@",result);            UIViewController *nowViewController = [self getCurrentVC];            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.02 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{                [nowViewController dismissViewControllerAnimated:NO completion:nil];                                cocos2d::LuaBridge::pushLuaFunctionById(_callBack);                cocos2d::LuaValueDict dict;                dict["scanResult"] = cocos2d::LuaValue::stringValue([result UTF8String]);                cocos2d::LuaBridge::getStack()->pushLuaValueDict(dict);                cocos2d::LuaBridge::getStack()->executeFunction(1);                cocos2d::LuaBridge::releaseLuaFunctionById(_callBack);            });        }    }];    [nowViewController presentViewController:vc animated:YES completion:nil];}
其中scanQRCode方法为最终lua掉用oc的方法,在扫描识别出二维码信息之后会将信息传回给lua端。

------------2.6lua掉用oc扫描二维码代码:

    local callBack = function (message)        print("message scanResult : ", message.scanResult)        Utils.showTip(message.scanResult)    end    local info = {listener = callBack}    luaoc.callStaticMethod("AppController", "scanQRCode", info)
------------2.7添加依赖框架
如上1.4,扫描二维码需要添加框架AVFoundation, CoreMedie, CoreVideo, QuartzCore, libiconv

-----3.扫描界面横竖屏说明

如果游戏界面是横屏的,而二维码扫描界面要求是竖屏的,则需要做些操作。

------------3.1增加竖屏支持

项目->TARGETS->General->Deployment Info->Device Orientation->勾选Portrait,Landscape Left, Landscape Right。

------------3.2让游戏界面只支持横屏

项目->frameworks->runtime-src->proj.ios_mac->ios->RootViewController.mmsupportedInterfaceOrientations方法修改为:

// For ios6, use supportedInterfaceOrientations & shouldAutorotate instead- (NSUInteger) supportedInterfaceOrientations{    return UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight;//#ifdef __IPHONE_6_0//    return UIInterfaceOrientationMaskAllButUpsideDown;//#endif}
------------3.3扫描二维码界面只支持竖屏

项目->frameworks->runtime-src->proj.ios_mac->ios->ZCZBarViewController.mm中增加代码

////支持旋转//-(BOOL)shouldAutorotate{//    return NO;//}////支持的方向//- (UIInterfaceOrientationMask)supportedInterfaceOrientations {//    return UIInterfaceOrientationMaskPortrait;//}
------------3.4修改view界面width和height重新适配
项目->frameworks->runtime-src->proj.ios_mac->ios->ZCZBarViewController.mm中将

#define WIDTH#define HEIGHT两个宏的值颠倒下

-----4.关于项目->frameworks->runtime-src->proj.ios_mac->ios->ZCZBarViewController.mm#define WIDTH#define HEIGHT两个宏

本来因该是

#define WIDTH [UIScreen mainScreen].bounds.size.width

#define HEIGHT [UIScreen mainScreen].bounds.size.height

但在iphone4s(ios6.1.3)上取出的width和height为320, 480,而在iPhone6 Plus(ios10.2)上width和height为568, 320。

一个宽小于高,一个宽大于高,使得4s横屏的时候,6Plus竖屏是对的,而在6Plus上横屏就是乱的。

所以后来将两个宏修改为(注意:两边一定要带括号,防止编译时宏展开后由于操作符优先级导致的运算错误)

#define WIDTH ( ([UIScreen mainScreen].bounds.size.width>[UIScreen mainScreen].bounds.size.height)?[UIScreen mainScreen].bounds.size.width:[UIScreen mainScreen].bounds.size.height )
#define 
HEIGHT ( ([UIScreen mainScreen].bounds.size.width<[UIScreen mainScreen].bounds.size.height)?[UIScreen mainScreen].bounds.size.width:[UIScreen mainScreen].bounds.size.height )

从而将固定取获得的二者较大值为二者较小值。若是竖屏,则反过来。

-----5.遇到的一些问题

------------5.1对于ZCZBarViewController.mm中的initCpture方法中有句

AVAuthorizationStatus authStatus = [AVCaptureDeviceauthorizationStatusForMediaType:mediaType];

注意:此方法只对ios7以上的系统有用,如果是在ios6的系统的话就直接崩溃了,况且ios6上也没有“设置--隐私--相机”那一项。

所以加了if(IOS7)的判断。

------------5.2若碰到错误Cannot synthesize weak property in file using manual reference counting 
项目->TARGETS->Build Settings->Apple LLVM 8.0-Language-Objective C->Weak References in Manual Retian Release改为YES

------------5.3编译报错XXXX.o

若编译运行报错,XXXX.o什么什么的问题,则可能是有依赖框架没有导入。

-----6.参考链接

//原生生成二维码

http://blog.csdn.net/zhuming3834/article/details/50832953

//原生二维码扫描

http://www.cocoachina.com/ios/20161009/17696.html

//zBar下载地址

http://download.csdn.net/download/kid_devil/7552613

//zBarDemo下载地址

http://download.csdn.net/detail/shan1991fei/9474417

//二维码扫描之zXing与zBar的优劣

http://blog.csdn.net/l_215851356/article/details/51898514





0 0
原创粉丝点击