首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

iOS 二維碼生成與掃描全攻略:CoreImage 與 AVFoundation 實戰

     編輯:Java 相關知識

前言

二維碼廣泛應用於支付、登錄、分享等場景。iOS 原生框架 CoreImage(生成)與 AVFoundation(掃描)提供了高效、零依賴的實現方案。本文詳解兩大核心流程及關鍵代碼。

一、生成二維碼

支持內容類型

  • 純文本
  • 聯繫人名片
  • URL(帶協議頭可直接跳轉瀏覽器)

CoreImage 生成步驟

  1. 導入 <CoreImage/CoreImage.h>
  2. 創建濾鏡:CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
  3. 恢復默認屬性:[filter setDefaults];
  4. 設置內容:將字符串轉 NSData (UTF-8),通過 KVO 設置 inputMessage
  5. 獲取輸出 CIImage
  6. 顯示或轉高清 UIImage

基礎代碼

CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
[filter setDefaults];
NSString *str = @"這是一個二維碼生成結果";
NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];
[filter setValue:data forKey:@"inputMessage"];
CIImage *outputImage = [filter outputImage];
self.imageView.image = [UIImage imageWithCIImage:outputImage];

高清圖片生成(解決模糊)

默認輸出較小,需按比例放大並關閉插值:

- (UIImage *)createNonInterpolatedUIImageFormCIImage:(CIImage *)image withSize:(CGFloat)size {
    CGRect extent = CGRectIntegral(image.extent);
    CGFloat scale = MIN(size / CGRectGetWidth(extent), size / CGRectGetHeight(extent));
    size_t width = CGRectGetWidth(extent) * scale;
    size_t height = CGRectGetHeight(extent) * scale;
    CGColorSpaceRef cs = CGColorSpaceCreateDeviceGray();
    CGContextRef bitmapRef = CGBitmapContextCreate(nil, width, height, 8, 0, cs, kCGImageAlphaNone);
    CIContext *context = [CIContext contextWithOptions:nil];
    CGImageRef bitmapImage = [context createCGImage:image fromRect:extent];
    CGContextSetInterpolationQuality(bitmapRef, kCGInterpolationNone);
    CGContextScaleCTM(bitmapRef, scale, scale);
    CGContextDrawImage(bitmapRef, extent, bitmapImage);
    CGImageRef scaledImage = CGBitmapContextCreateImage(bitmapRef);
    CGContextRelease(bitmapRef);
    CGImageRelease(bitmapImage);
    return [UIImage imageWithCGImage:scaledImage];
}

調用:UIImage *hdQR = [self createNonInterpolatedUIImageFormCIImage:outputImage withSize:300];

URL 協議頭自動跳轉

NSString *url = @"https://www.baidu.com"; // 必須帶 https:// 或 https://
// 生成的二維碼掃描後系統會提示打開瀏覽器

二、掃描二維碼

AVFoundation 掃描流程

  1. 創建捕獲會話 AVCaptureSession
  2. 添加輸入設備:AVCaptureDevice (後置鏡頭) → AVCaptureDeviceInput
  3. 添加輸出元數據:AVCaptureMetadataOutput,設置代理、隊列、元數據類型 AVMetadataObjectTypeQRCode
  4. 添加預覽圖層:AVCaptureVideoPreviewLayer 關聯 session,加到 view
  5. 開始運行:[session startRunning]
  6. 代理回調:captureOutput:didOutputMetadataObjects:fromConnection: 獲取掃描結果

完整代碼

@interface ViewController () <AVCaptureMetadataOutputObjectsDelegate>
@property (nonatomic, strong) AVCaptureVideoPreviewLayer *layer;
@property (nonatomic, strong) AVCaptureSession *session;
@end

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    AVCaptureSession *session = [[AVCaptureSession alloc] init];
    self.session = session;

    // 輸入
    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];
    [session addInput:input];

    // 輸出
    AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc] init];
    [output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
    [session addOutput:output];
    [output setMetadataObjectTypes:@[AVMetadataObjectTypeQRCode]];

    // 預覽圖層
    AVCaptureVideoPreviewLayer *layer = [AVCaptureVideoPreviewLayer layerWithSession:session];
    layer.frame = self.view.bounds;
    [self.view.layer addSublayer:layer];
    self.layer = layer;

    [session startRunning];
}

- (void)captureOutput:(AVCaptureOutput *)captureOutput 
didOutputMetadataObjects:(NSArray *)metadataObjects 
fromConnection:(AVCaptureConnection *)connection {
    if (metadataObjects.count > 0) {
        AVMetadataMachineReadableCodeObject *obj = metadataObjects.lastObject;
        NSLog(@"掃描結果: %@", obj.stringValue);
        [self.session stopRunning];
        [self.layer removeFromSuperlayer];
    } else {
        NSLog(@"未掃描到數據");
    }
}

三、進階優化建議

  1. 掃描框 UI:在 AVCaptureVideoPreviewLayer 上疊加半透明遮罩 + 掃描線動畫,提升用戶體驗。
  2. 只掃描指定區域:設置 output.rectOfInterest(歸一化坐標),減少計算量、提高速度。
  3. 燈光補光:[device lockForConfiguration:nil]; device.torchMode = AVCaptureTorchModeOn; [device unlockForConfiguration];
  4. 權限處理:Info.plist 添加 NSCameraUsageDescription,首次掃描前檢查授權狀態。
  5. 生成帶 Logo 二維碼:生成高清 QR 後,用 CGContextDrawImage 在中心繪製 Logo,注意 Logo 佔比不超 20% 且留白邊距。
  6. 識別率優化:對比度低、彎曲、遮擋場景可集成第三方庫(如 ZXing、WeChat OpenCV)作為備選。

總結

iOS 原生框架已足夠強大:CoreImage 生成 + AVFoundation 掃描,無需引入三方庫即可滿足 90%+ 業務場景。掌握高清渲染、掃描區域限制、權限適配等細節,即可構建生產級二維碼功能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved