掃描二維碼控制項的封裝,控制項封裝
掃描二維碼控制項的封裝
效果
源碼
https://github.com/YouXianMing/Animations
//// QRCodeView.h// QRCode//// Created by YouXianMing on 16/7/7.// Copyright © 2016年 XianMing You. All rights reserved.//#import <UIKit/UIKit.h>#import <AVFoundation/AVFoundation.h>@class QRCodeView;@protocol QRCodeViewDelegate <NSObject>@optional/** * 擷取QR的掃描結果 * * @param codeView QRCodeView實體物件 * @param codeString 掃描字串 */- (void)QRCodeView:(QRCodeView *)codeView codeString:(NSString *)codeString;@end@interface QRCodeView : UIView/** * 代理 */@property (nonatomic, weak) id <QRCodeViewDelegate> delegate;/** * 燈的狀態,預設為關閉 */@property (nonatomic) AVCaptureTorchMode torchMode;/** * 敏感地區,如果不設定,則為全部掃描地區 */@property (nonatomic) CGRect interestArea;/** * 你用來添加自訂控制項的view,尺寸與當前初始化的view一致 */@property (nonatomic, strong) UIView *contentView;/** * 正在運行當中 */@property (nonatomic, readonly) BOOL isRunning;/** * 開始掃描 * * @return 如果成功,則返回YES,否則返回NO */- (BOOL)start;/** * 結束掃描 */- (void)stop;@end
//// QRCodeView.m// QRCode//// Created by YouXianMing on 16/7/7.// Copyright © 2016年 XianMing You. All rights reserved.//#import "QRCodeView.h"@interface QRCodeView () <AVCaptureMetadataOutputObjectsDelegate>@property (nonatomic) BOOL isRunning;@property (nonatomic, strong) UIView *videoView;@property (nonatomic, strong) AVCaptureDeviceInput *deviceInput;@property (nonatomic, strong) AVCaptureDevice *captureDevice;@property (nonatomic, strong) AVCaptureSession *captureSession;@property (nonatomic, strong) AVCaptureVideoPreviewLayer *videoPreviewLayer;@property (nonatomic, strong) AVCaptureMetadataOutput *captureMetadataOutput;@end@implementation QRCodeView- (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { self.videoView = [[UIView alloc] initWithFrame:self.bounds]; [self addSubview:self.videoView]; self.contentView = [[UIView alloc] initWithFrame:self.bounds]; [self addSubview:self.contentView]; self.captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; _torchMode = AVCaptureTorchModeOff; [self addNotificationCenter]; } return self;}#pragma mark - NSNotificationCenter related.- (void)addNotificationCenter { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notificationCenterEvent:) name:AVCaptureInputPortFormatDescriptionDidChangeNotification object:nil];}- (void)removeNotificationCenter { [[NSNotificationCenter defaultCenter] removeObserver:self name:AVCaptureInputPortFormatDescriptionDidChangeNotification object:nil];}- (void)notificationCenterEvent:(NSNotification *)sender { if (self.interestArea.size.width && self.interestArea.size.height) { self.captureMetadataOutput.rectOfInterest = [self.videoPreviewLayer metadataOutputRectOfInterestForRect:self.interestArea]; } else { self.captureMetadataOutput.rectOfInterest = CGRectMake(0, 0, 1, 1); }}#pragma mark - Start & Stop.- (BOOL)start { // 初始化輸入資料流 BOOL result = NO; NSError *error = nil; self.deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:self.captureDevice error:&error]; if (self.deviceInput == nil) { NSLog(@"%@", error); return result; } // 建立會話 self.captureSession = [[AVCaptureSession alloc] init]; // 添加輸入資料流 [self.captureSession addInput:self.deviceInput]; // 初始化輸出資料流 self.captureMetadataOutput = [[AVCaptureMetadataOutput alloc] init]; // 添加輸出資料流 [self.captureSession addOutput:self.captureMetadataOutput]; // 建立queue. [self.captureMetadataOutput setMetadataObjectsDelegate:self queue:dispatch_queue_create(nil, nil)]; self.captureMetadataOutput.metadataObjectTypes = @[AVMetadataObjectTypeQRCode]; // 建立輸出對象 self.videoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.captureSession]; self.videoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; self.videoPreviewLayer.frame = self.contentView.bounds; [self.videoView.layer addSublayer:self.videoPreviewLayer]; // 開始 [self.captureSession startRunning]; self.isRunning = YES; result = YES; return result;}- (void)stop { [self.captureSession stopRunning]; self.isRunning = NO; self.captureSession = nil;}#pragma mark - AVCaptureMetadataOutputObjectsDelegate- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection { if (metadataObjects.count > 0) { AVMetadataMachineReadableCodeObject *metadata = metadataObjects.firstObject; NSString *result = nil; if ([metadata.type isEqualToString:AVMetadataObjectTypeQRCode]) { result = metadata.stringValue; if (_delegate && [_delegate respondsToSelector:@selector(QRCodeView:codeString:)]) { [_delegate QRCodeView:self codeString:result]; } } }}#pragma mark - Setter & Getter.- (void)setTorchMode:(AVCaptureTorchMode)torchMode { _torchMode = torchMode; if (_deviceInput && [self.captureDevice hasTorch]) { [self.captureDevice lockForConfiguration:nil]; [self.captureDevice setTorchMode:torchMode]; [self.captureDevice unlockForConfiguration]; }}#pragma mark - System method.- (void)dealloc { [self stop]; [self removeNotificationCenter];}@end