天天看點

實作類似qq掃一掃功能

最近公司項目需要實作一個類似qq掃一掃功能,該功能主要分為三個部分:掃一掃、掃描相冊中二維碼圖檔、開燈(我的二維碼不是主要功能)

1.掃一掃

iOS7以後,AVFoundation.framework架構支援掃一掃功能,詳細代碼,可以參考http://www.jianshu.com/p/6b7d54b3f88b

但該部落格中的代碼隻能簡單的實作掃一掃功能,周圍的背景并不是半透明的。

實作類似qq掃一掃功能

通過以下代碼可以實作中間透明,旁邊半透明的效果

實作類似qq掃一掃功能
-(void)setupBgView{
    self.view.backgroundColor = [UIColor blackColor];
    //繪制掃一掃背景,中間透明,旁邊半透明
    UIGraphicsBeginImageContext(self.view.frame.size);
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGContextSetRGBFillColor(ctx, 0,0,0,0.5);
    CGRect drawRect =CGRectMake(0, 0, Screen_Width, Screen_height);
    
    //draw the transparent layer
    CGContextFillRect(ctx, drawRect);
    
    //clear the center rect  of the layer
    drawRect = self.scanBg.frame;
    CGContextClearRect(ctx, drawRect);
    
    UIImage* returnimage = UIGraphicsGetImageFromCurrentImageContext();
    UIImageView * img = [[UIImageView alloc] initWithImage:returnimage];
    [self.view addSubview:img];
    UIGraphicsEndImageContext();
}
           

但以上代碼仍然存在一點小問題:這張背景圖檔是直接蓋在最上層,導緻掃一掃界面上的圖檔和文字效果不好(左圖)。

實作類似qq掃一掃功能

隻需将背景圖檔移到視圖的最上層即可(右圖):

[self.view addSubview:img];
    [self.view sendSubviewToBack:img];
           

2.掃描相冊中二維碼圖檔

在網上尋找了很久,發現AVFoundation.framework架構并不支援掃描相冊中二維碼圖檔功能。

于是,開始尋找支援掃描相冊中二維碼圖檔的第三方類庫,目前隻有ZBar和ZXingObjC支援,而前者很久沒更新,故而選擇後者。

通過以下代碼可以實作點選相冊,選擇圖檔,擷取圖檔中的二維碼資訊。

- (IBAction)clickPhotoAlbum:(id)sender 
{
    UIImagePickerController *picker = [[UIImagePickerController alloc] init];
    picker.allowsEditing = YES;
    picker.delegate = self;
    picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
    [self presentViewController:picker animated:YES completion:^{}];
}
#pragma mark - UIImagePickerControllerDelegate
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    UIImage *image = [info objectForKey:@"UIImagePickerControllerEditedImage"];
    [self dismissViewControllerAnimated:YES completion:^{
        [self getURLWithImage:image];
    }
    ];

}
-(void)getURLWithImage:(UIImage *)img{
    
    UIImage *loadImage= img;
    CGImageRef imageToDecode = loadImage.CGImage;
    
    ZXLuminanceSource *source = [[ZXCGImageLuminanceSource alloc] initWithCGImage:imageToDecode];
    ZXBinaryBitmap *bitmap = [ZXBinaryBitmap binaryBitmapWithBinarizer:[ZXHybridBinarizer binarizerWithSource:source]];
    
    NSError *error = nil;
    
    ZXDecodeHints *hints = [ZXDecodeHints hints];
    
    ZXMultiFormatReader *reader = [ZXMultiFormatReader reader];
    ZXResult *result = [reader decode:bitmap
                                hints:hints
                                error:&error];
    if (result) {
        // The coded result as a string. The raw data can be accessed with
        // result.rawBytes and result.length.
        NSString *contents = result.text;
        NSLog(@"contents =%@",contents);
        UIAlertView *alter = [[UIAlertView alloc] initWithTitle:@"解析成功" message:contents delegate:nil cancelButtonTitle:@"确定" otherButtonTitles: nil];
        [alter show];

    } else {
        UIAlertView *alter1 = [[UIAlertView alloc] initWithTitle:@"解析失敗" message:nil delegate:nil cancelButtonTitle:@"确定" otherButtonTitles: nil];
        [alter1 show];
    }
}
           

但,以上代碼存在一點小問題,跳轉到相冊後,選擇一張圖檔,這張圖檔是可編輯的狀态

實作類似qq掃一掃功能
picker.allowsEditing = YES;
           

改為

picker.allowsEditing = NO;
           

結果,閃退。調試發現跳轉到以下代碼,image為空。

UIImage *image = [info objectForKey:@"UIImagePickerControllerEditedImage"];
           

列印info,發現info中還有UIImagePickerControllerOriginalImage,将image該為UIImagePickerControllerOriginalImage即可。

UIImage *image = [info objectForKey:@"UIImagePickerControllerOriginalImage"];
           

3.開燈

這裡的開燈其實就是打開手電筒,手電筒也是基于AVFoundation.framework架構,通過以下代碼可以實作開燈和關燈功能。

- (IBAction)clickLight:(id)sender {
    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    if ([device hasTorch]) {
        [device lockForConfiguration:nil];
        if(isLedOn){
            //關燈
            [device setTorchMode: AVCaptureTorchModeOff];
        }else{
            //開燈
            [device setTorchMode: AVCaptureTorchModeOn];
        }
        
        [device unlockForConfiguration];
    }
    isLedOn = !isLedOn;
}
           

但是,光有以上代碼是不夠的,在離開掃一掃界面時,如果沒有關閉手電筒,手電筒一直會是開啟的狀态。這時,需要添加以下代碼,在離開頁面時,關閉手電筒。

-(void)viewWillDisappear:(BOOL)animated{
    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    if ([device hasTorch]) {
        [device lockForConfiguration:nil];
        [device setTorchMode: AVCaptureTorchModeOff];
        
        [device unlockForConfiguration];
    }
    isLedOn = NO;
}
           

以上三部分代碼,即可完成類似qq掃一掃功能。