oc 扫码

作者: 喵喵粉 | 来源:发表于2021-04-02 15:33 被阅读0次
    1. 使用相机扫码
    2. 扫描相册

    1. 使用相机扫码

    1. 相机授权
    2. 用到UIView的扩展
      UIViewExt.h
    #import <UIKit/UIKit.h>
    
    CGPoint CGRectGetCenter(CGRect rect);
    CGRect  CGRectMoveToCenter(CGRect rect, CGPoint center);
    
    @interface UIView (ViewFrameGeometry)
    @property CGPoint origin;
    @property CGSize size;
    
    @property (readonly) CGPoint bottomLeft;
    @property (readonly) CGPoint bottomRight;
    @property (readonly) CGPoint topRight;
    
    @property CGFloat height;
    @property CGFloat width;
    
    @property CGFloat top;
    @property CGFloat left;
    
    @property CGFloat bottom;
    @property CGFloat right;
    
    - (void) moveBy: (CGPoint) delta;
    - (void) scaleBy: (CGFloat) scaleFactor;
    - (void) fitInSize: (CGSize) aSize;
    - (UIViewController *)viewController;
    @end
    

    UIViewExt.m

    CGPoint CGRectGetCenter(CGRect rect)
    {
        CGPoint pt;
        pt.x = CGRectGetMidX(rect);
        pt.y = CGRectGetMidY(rect);
        return pt;
    }
    
    CGRect CGRectMoveToCenter(CGRect rect, CGPoint center)
    {
        CGRect newrect = CGRectZero;
        newrect.origin.x = center.x-CGRectGetMidX(rect);
        newrect.origin.y = center.y-CGRectGetMidY(rect);
        newrect.size = rect.size;
        return newrect;
    }
    
    @implementation UIView (ViewGeometry)
    
    // Retrieve and set the origin
    - (CGPoint) origin
    {
        return self.frame.origin;
    }
    
    - (void) setOrigin: (CGPoint) aPoint
    {
        CGRect newframe = self.frame;
        newframe.origin = aPoint;
        self.frame = newframe;
    }
    
    
    // Retrieve and set the size
    - (CGSize) size
    {
        return self.frame.size;
    }
    
    - (void) setSize: (CGSize) aSize
    {
        CGRect newframe = self.frame;
        newframe.size = aSize;
        self.frame = newframe;
    }
    
    // Query other frame locations
    - (CGPoint) bottomRight
    {
        CGFloat x = self.frame.origin.x + self.frame.size.width;
        CGFloat y = self.frame.origin.y + self.frame.size.height;
        return CGPointMake(x, y);
    }
    
    - (CGPoint) bottomLeft
    {
        CGFloat x = self.frame.origin.x;
        CGFloat y = self.frame.origin.y + self.frame.size.height;
        return CGPointMake(x, y);
    }
    
    - (CGPoint) topRight
    {
        CGFloat x = self.frame.origin.x + self.frame.size.width;
        CGFloat y = self.frame.origin.y;
        return CGPointMake(x, y);
    }
    
    
    // Retrieve and set height, width, top, bottom, left, right
    - (CGFloat) height
    {
        return self.frame.size.height;
    }
    
    - (void) setHeight: (CGFloat) newheight
    {
        CGRect newframe = self.frame;
        newframe.size.height = newheight;
        self.frame = newframe;
    }
    
    - (CGFloat) width
    {
        return self.frame.size.width;
    }
    
    - (void) setWidth: (CGFloat) newwidth
    {
        CGRect newframe = self.frame;
        newframe.size.width = newwidth;
        self.frame = newframe;
    }
    
    - (CGFloat) top
    {
        return self.frame.origin.y;
    }
    
    - (void) setTop: (CGFloat) newtop
    {
        CGRect newframe = self.frame;
        newframe.origin.y = newtop;
        self.frame = newframe;
    }
    
    - (CGFloat) left
    {
        return self.frame.origin.x;
    }
    
    - (void) setLeft: (CGFloat) newleft
    {
        CGRect newframe = self.frame;
        newframe.origin.x = newleft;
        self.frame = newframe;
    }
    
    - (CGFloat) bottom
    {
        return self.frame.origin.y + self.frame.size.height;
    }
    
    - (void) setBottom: (CGFloat) newbottom
    {
        CGRect newframe = self.frame;
        newframe.origin.y = newbottom - self.frame.size.height;
        self.frame = newframe;
    }
    
    - (CGFloat) right
    {
        return self.frame.origin.x + self.frame.size.width;
    }
    
    - (void) setRight: (CGFloat) newright
    {
        CGFloat delta = newright - (self.frame.origin.x + self.frame.size.width);
        CGRect newframe = self.frame;
        newframe.origin.x += delta ;
        self.frame = newframe;
    }
    
    // Move via offset
    - (void) moveBy: (CGPoint) delta
    {
        CGPoint newcenter = self.center;
        newcenter.x += delta.x;
        newcenter.y += delta.y;
        self.center = newcenter;
    }
    
    // Scaling
    - (void) scaleBy: (CGFloat) scaleFactor
    {
        CGRect newframe = self.frame;
        newframe.size.width *= scaleFactor;
        newframe.size.height *= scaleFactor;
        self.frame = newframe;
    }
    
    // Ensure that both dimensions fit within the given size by scaling down
    - (void) fitInSize: (CGSize) aSize
    {
        CGFloat scale;
        CGRect newframe = self.frame;
        
        if (newframe.size.height && (newframe.size.height > aSize.height))
        {
            scale = aSize.height / newframe.size.height;
            newframe.size.width *= scale;
            newframe.size.height *= scale;
        }
        
        if (newframe.size.width && (newframe.size.width >= aSize.width))
        {
            scale = aSize.width / newframe.size.width;
            newframe.size.width *= scale;
            newframe.size.height *= scale;
        }                                                           
        
        self.frame = newframe;  
    }
    - (UIViewController *)viewController
    {
        //获得下一个事件响应者
        UIResponder *next = [self nextResponder];
        
        do {
            if ([next isKindOfClass:[UIViewController class]]) {
                return (UIViewController *)next;
            }
            
            next = [next nextResponder];
            
        } while (next != nil);
        
        return nil;
    }
    @end
    
    1. 新建vc:ScanQRCodeVC
      ScanQRCodeVC.h
    #import <UIKit/UIKit.h>
    
    NS_ASSUME_NONNULL_BEGIN
    
    //typedef void (^DoneBlock)(NSString *code);
    //@property (nonatomic, copy) DoneBlock doneBlock;
    
    @interface ScanQRCodeVC : UIViewController
    
    - (instancetype)initWithScanDone:(void (^)(NSString *code))done;
    
    @end
    
    NS_ASSUME_NONNULL_END
    

    ScanQRCodeVC.m

    #import "ScanQRCodeVC.h"
    #import <AVFoundation/AVFoundation.h>
    #import "UIViewExt.h"
    #import "CameraPrivateObj.h"
    
    @interface ScanQRCodeVC ()<AVCaptureMetadataOutputObjectsDelegate>
    @property (nonatomic, strong) AVCaptureDevice *device;
    @property (nonatomic, strong) AVCaptureDeviceInput *input;
    @property (nonatomic, strong) AVCaptureMetadataOutput *output;
    @property (nonatomic, strong) AVCaptureSession *session;
    @property (nonatomic, strong) AVCaptureVideoPreviewLayer *preview;
    
    @property (nonatomic, strong) UIImageView *ivRedLine;
    @property (nonatomic, assign) NSInteger count;
    
    @property (nonatomic, copy) void (^doneBlock)(NSString *);
    @end
    
    @implementation ScanQRCodeVC
    
    - (instancetype)initWithScanDone:(void (^)(NSString *code))done {
        if (self = [super initWithNibName:nil bundle:nil]) {
            self.doneBlock = done;
        }
        return self;
    }
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view.
        
        self.view.backgroundColor = [UIColor blackColor];
        
        [self cameraAuth];
        [self setupUI];
    }
    
    #pragma mark - init
    
    - (void)cameraAuth {
        [CameraPrivateObj extCameraPermissions:^{
            [self setupCamera];
        } failed:^(NSString * _Nonnull desc) {
            NSLog(@"%@", desc);
        } deniedBlock:^{
            NSString *tips = NSLocalizedString(@"AVAuthorization", @"您没有权限访问相机");
            UIAlertController *alert = [UIAlertController alertControllerWithTitle:tips message:nil preferredStyle:UIAlertControllerStyleAlert];
            [alert addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
                // 点击取消
            }]];
            [alert addAction:[UIAlertAction actionWithTitle:@"去设置" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
                // 点击确定
                if (@available(iOS 10.0, *)) {
                    [UIApplication.sharedApplication openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString] options:@{} completionHandler:nil];
                } else {
                    [UIApplication.sharedApplication openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
                }
            }]];
            [self presentViewController:alert animated:YES completion:nil];
        }];
    }
    
    - (void)setupUI {
        CGFloat kScreenWidth = UIScreen.mainScreen.bounds.size.width;
        CGFloat kScreenHeight = UIScreen.mainScreen.bounds.size.height;
        CGFloat kStateBarHeight = CGRectGetHeight([UIApplication sharedApplication].statusBarFrame);
        CGFloat kNavBarHeight = 44;
        CGFloat kWidthRation = (kScreenWidth/320.f);
        CGFloat scanWidth = 250.f;
        
        CGPoint center = CGPointMake(kScreenWidth/2.f, kStateBarHeight +kNavBarHeight +30*kWidthRation+scanWidth/2.f);
        UIImageView *barImage1 = [[UIImageView alloc]initWithFrame:CGRectMake(center.x-scanWidth/2.f, center.y-scanWidth/2.f, 25, 25)];
        barImage1.image = [UIImage imageNamed:@"img_bar1.png"];
        [self.view addSubview:barImage1];
        
        UIImageView *barImage2 = [[UIImageView alloc]initWithFrame:CGRectMake(center.x+scanWidth/2.f-25, center.y-scanWidth/2.f, 25, 25)];
        barImage2.image = [UIImage imageNamed:@"img_bar2.png"];
        [self.view addSubview:barImage2];
    
        UIImageView *barImage3 = [[UIImageView alloc]initWithFrame:CGRectMake(center.x-scanWidth/2.f, center.y+scanWidth/2.f-25, 25, 25)];
        barImage3.image = [UIImage imageNamed:@"img_bar3.png"];
        [self.view addSubview:barImage3];
    
        UIImageView *barImage4 = [[UIImageView alloc]initWithFrame:CGRectMake(center.x+scanWidth/2.f-25, center.y+scanWidth/2.f-25, 25, 25)];
        barImage4.image = [UIImage imageNamed:@"img_bar4.png"];
        [self.view addSubview:barImage4];
    
        _ivRedLine = [[UIImageView alloc]initWithFrame:CGRectMake(center.x-240/2.f, center.y - scanWidth/2.f+5, 240, 5)];
        _ivRedLine.image = [UIImage imageNamed:@"img_RQcode_line.png"];
        _ivRedLine.hidden = YES;
        [self.view addSubview:_ivRedLine];
        
        UIView *viewO = [[UIView alloc]initWithFrame:CGRectMake(0, 0, self.view.width, barImage1.top)];
        viewO.backgroundColor = [[UIColor blackColor]colorWithAlphaComponent:0.7];
        [self.view addSubview:viewO];
        
        UIView *viewT = [[UIView alloc]initWithFrame:CGRectMake(0, barImage1.top, barImage1.left, scanWidth)];
        viewT.backgroundColor = [[UIColor blackColor]colorWithAlphaComponent:0.7];
        [self.view addSubview:viewT];
        
        UIView *viewS = [[UIView alloc]initWithFrame:CGRectMake(barImage2.right, barImage1.top, kScreenWidth - barImage2.right, scanWidth)];
        viewS.backgroundColor = [[UIColor blackColor]colorWithAlphaComponent:0.7];
        [self.view addSubview:viewS];
        
        UIView *viewF = [[UIView alloc]initWithFrame:CGRectMake(0, barImage3.bottom, kScreenWidth, kScreenHeight-barImage3.bottom)];
        viewF.backgroundColor = [[UIColor blackColor]colorWithAlphaComponent:0.7];
        [self.view addSubview:viewF];
        
        
        // line移动的范围为 一个扫码框的高度(由于图片问题再减去图片的高度)
        CABasicAnimation * lineAnimation = [self animationWith:@(0) toValue:@(scanWidth-15) repCount:MAXFLOAT duration:1.5f];
        [_ivRedLine.layer addAnimation:lineAnimation forKey:@"LineImgViewAnimation"];
        
    //    dispatch_async(dispatch_get_global_queue(0, 0), ^{
    //        dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC));
    //        dispatch_after(popTime, dispatch_get_main_queue(), ^(void) {
    //            [self setupCamera];
    //        });
    //    });
    }
    
    - (void)statCamera {
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC));
            dispatch_after(popTime, dispatch_get_main_queue(), ^(void) {
                [self setupCamera];
            });
        });
    }
    
    #pragma mark - 扫码line滑动动画
    - (CABasicAnimation*)animationWith:(id)fromValue toValue:(id)toValue repCount:(CGFloat)repCount duration:(CGFloat)duration {
        
        CABasicAnimation *lineAnimation = [CABasicAnimation animationWithKeyPath:@"transform.translation.y"];
        lineAnimation.fromValue = fromValue;
        lineAnimation.toValue = toValue;
        lineAnimation.repeatCount = repCount;
        lineAnimation.duration = duration;
        lineAnimation.fillMode = kCAFillModeForwards;
        lineAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
        lineAnimation.removedOnCompletion = NO;
        
        return lineAnimation;
    }
    //暂停动画
    - (void)pauseAnimation {
        //(0-5)
        CFTimeInterval pauseTime = [_ivRedLine.layer convertTime:CACurrentMediaTime() fromLayer:nil];
        _ivRedLine.layer.timeOffset = pauseTime;
        _ivRedLine.layer.speed = 0;
    }
    -(void)backAction{
        [self.navigationController popViewControllerAnimated:YES];
        [_session stopRunning];
        _ivRedLine = nil;
    }
    
    - (void)setupCamera {
        _ivRedLine.hidden = NO;
        // Device
        _device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
        
        // Input
        _input = [AVCaptureDeviceInput deviceInputWithDevice:self.device error:nil];
        
        // Output
        _output = [[AVCaptureMetadataOutput alloc]init];
        [_output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
        
        // Session
        _session = [[AVCaptureSession alloc]init];
        [_session setSessionPreset:AVCaptureSessionPresetHigh];
        if ([_session canAddInput:self.input])
        {
            [_session addInput:self.input];
        }
        
        if ([_session canAddOutput:self.output])
        {
            [_session addOutput:self.output];
        }
        
        // 条码类型 AVMetadataObjectTypeQRCode
        _output.metadataObjectTypes =@[AVMetadataObjectTypeUPCECode,
                                       AVMetadataObjectTypeCode39Code,
                                       AVMetadataObjectTypeCode39Mod43Code,
                                       AVMetadataObjectTypeEAN13Code,
                                       AVMetadataObjectTypeEAN8Code,
                                       AVMetadataObjectTypeCode93Code,
                                       AVMetadataObjectTypeCode128Code,
                                       AVMetadataObjectTypePDF417Code,
                                       AVMetadataObjectTypeQRCode,
                                       AVMetadataObjectTypeAztecCode];
        CGFloat kScreenWidth = UIScreen.mainScreen.bounds.size.width;
        CGFloat kScreenHeight = UIScreen.mainScreen.bounds.size.height;
        [_output setRectOfInterest:CGRectMake((64+20)/kScreenHeight, ((kScreenWidth-240)/2)/kScreenWidth, 240/kScreenHeight, 240/kScreenWidth)];
        // Preview
        _preview =[AVCaptureVideoPreviewLayer layerWithSession:self.session];
        _preview.videoGravity = AVLayerVideoGravityResizeAspectFill;
     
        _preview.frame = self.view.layer.bounds;
        [self.view.layer insertSublayer:self.preview atIndex:0];
        // Start
        [_session startRunning];
    }
    
    
    #pragma mark - AVCaptureMetadataOutputObjectsDelegate
    
    - (void)captureOutput:(AVCaptureOutput *)output didOutputMetadataObjects:(NSArray<__kindof AVMetadataObject *> *)metadataObjects fromConnection:(AVCaptureConnection *)connection {
        [_session stopRunning];
        
        [self pauseAnimation];
        NSString *stringValue = @"";
        
        if ([metadataObjects count] >0)
        {
            AVMetadataMachineReadableCodeObject * metadataObject = [metadataObjects objectAtIndex:0];
            stringValue = [NSString stringWithFormat:@"%@", metadataObject.stringValue];
        }
        
        if (self.count>0) {
            return;
        }
    
        _count++;
        
        NSLog(@"%@ count:%ld", stringValue, (long)_count);
        
        if (self.doneBlock) {
            self.doneBlock(stringValue);
        }
        
        [self.navigationController popViewControllerAnimated:YES];
    }
    
    
    @end
    
    1. 使用
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    //    ScanQRCodeVC *vc = [ScanQRCodeVC new];
    //    vc.doneBlock = ^(NSString * _Nonnull code) {
    //        NSLog(@"扫码的code:%@", code);
    //    };
        
        ScanQRCodeVC *vc = [[ScanQRCodeVC alloc] initWithScanDone:^(NSString * _Nonnull code) {
            NSLog(@"扫码的code:%@", code);
        }];
        [self.navigationController pushViewController:vc animated:YES];
    }
    

    2. 扫描相册

    - (void)scanLocalDemo {
        [CameraPrivateObj extPhotoPermissions:^{
            [self scanFromImage:[UIImage imageNamed:@"abd"]];
        } failed:^(NSString * _Nonnull desc) {
            NSLog(@"%@", desc);
        } deniedBlock:^{
            NSLog(@"denied");
        }];
    }
    
    - (void)scanFromImage:(UIImage *)image {
        //
        NSData *data = UIImageJPEGRepresentation(image, 1);
        CIImage *ciImage = [CIImage imageWithData:data];
        CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:nil options:@{CIDetectorAccuracy: CIDetectorAccuracyHigh, CIDetectorImageOrientation:@1}];
        NSArray<CIFeature *> *features = [detector featuresInImage:ciImage];
        for (CIFeature *feature in features) {
            NSLog(@"%@", feature);
            
            if ([feature isKindOfClass:[CIQRCodeFeature class]]) {
                CIQRCodeFeature *ft = (CIQRCodeFeature *)feature;
                NSLog(@"二维码:%@", ft.messageString);
            } else if ([feature isKindOfClass:[CITextFeature class]]) {
                CITextFeature *ft = (CITextFeature *)feature;
                NSLog(@"文本:%@", ft.subFeatures);
            } else {
                NSLog(@"other");
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:oc 扫码

          本文链接:https://www.haomeiwen.com/subject/nocqkltx.html