add qrcode界面和功能

This commit is contained in:
cebgcontract 2022-11-25 15:08:47 +08:00
parent 7c78c22dab
commit 4b45e34627
63 changed files with 6625 additions and 122 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 336 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 938 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 980 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 956 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 801 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 B

View File

@ -0,0 +1,9 @@
//
// CreateBarCodeViewController.h
// LBXScanDemo
#import <UIKit/UIKit.h>
@interface CreateBarCodeViewController : UIViewController
@end

View File

@ -0,0 +1,181 @@
//
// CreateBarCodeViewController.m
// LBXScanDemo
//
#import "CreateBarCodeViewController.h"
#import "LBXScanNative.h"
#import "UIImageView+CornerRadius.h"
@interface CreateBarCodeViewController ()
//
@property (nonatomic, strong) UIView *qrView;
@property (nonatomic, strong) UIImageView* qrImgView;
@property (nonatomic, strong) UIImageView* logoImgView;
//
@property (nonatomic, strong) UIView *tView;
@property (nonatomic, strong) UIImageView *tImgView;
@end
@implementation CreateBarCodeViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
if ([self respondsToSelector:@selector(setEdgesForExtendedLayout:)]) {
self.edgesForExtendedLayout = UIRectEdgeNone;
}
self.view.backgroundColor = [UIColor whiteColor];
[self showSetttingButton];
}
- (void)showSetttingButton
{
//
//rightBarButtonItem
UIButton *rightBtn = [[UIButton alloc]initWithFrame:CGRectMake(0, 0, 40, 30)];
[rightBtn setTitle:@"切换" forState:UIControlStateNormal];
[rightBtn setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
[rightBtn addTarget:self action:@selector(newCodeChooose) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *rightCunstomButtonView = [[UIBarButtonItem alloc] initWithCustomView:rightBtn];
self.navigationItem.rightBarButtonItem = rightCunstomButtonView;
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
//
UIView *view = [[UIView alloc]initWithFrame:CGRectMake( (CGRectGetWidth(self.view.frame)-CGRectGetWidth(self.view.frame)*5/6)/2, 100, CGRectGetWidth(self.view.frame)*5/6, CGRectGetWidth(self.view.frame)*5/6)];
[self.view addSubview:view];
view.backgroundColor = [UIColor whiteColor];
view.layer.shadowOffset = CGSizeMake(0, 2);
view.layer.shadowRadius = 2;
view.layer.shadowColor = [UIColor blackColor].CGColor;
view.layer.shadowOpacity = 0.5;
self.qrImgView = [[UIImageView alloc]init];
_qrImgView.bounds = CGRectMake(0, 0, CGRectGetWidth(view.frame)-12, CGRectGetWidth(view.frame)-12);
_qrImgView.center = CGPointMake(CGRectGetWidth(view.frame)/2, CGRectGetHeight(view.frame)/2);
[view addSubview:_qrImgView];
self.qrView = view;
//
self.tView = [[UIView alloc]initWithFrame:CGRectMake( (CGRectGetWidth(self.view.frame)-CGRectGetWidth(self.view.frame)*5/6)/2,
100,
CGRectGetWidth(self.view.frame)*5/6,
CGRectGetWidth(self.view.frame)*5/6*0.5)];
[self.view addSubview:_tView];
self.tImgView = [[UIImageView alloc]init];
_tImgView.bounds = CGRectMake(0, 0, CGRectGetWidth(_tView.frame)-12, CGRectGetHeight(_tView.frame)-12);
_tImgView.center = CGPointMake(CGRectGetWidth(_tView.frame)/2, CGRectGetHeight(_tView.frame)/3);
[_tView addSubview:_tImgView];
[self createQR_logo];
}
- (void)newCodeChooose
{
__weak __typeof(self) weakSelf = self;
// [LBXAlertAction showActionSheetWithTitle:@"" message:nil cancelButtonTitle:@"取消" destructiveButtonTitle:nil otherButtonTitle:@[@"二维码+logo",@"二维码前景颜色+背景颜色",@"code13-商品条形码",@"支付宝付款条形码(code128)"] chooseBlock:^(NSInteger buttonIdx) {
//
// switch (buttonIdx) {
//
// case 1:
// [weakSelf createQR_logo];
// break;
// case 2:
// [weakSelf createQR_color];
// break;
// case 3:
// [weakSelf createCodeEAN13];
// break;
// case 4:
// [weakSelf createCode128];
// break;
//
// default:
// break;
// }
// }];
}
- (void)createQR_logo
{
_qrView.hidden = NO;
_tView.hidden = YES;
_qrImgView.image = [LBXScanNative createQRWithString:@"lbxia20091227@foxmail.com" QRSize:_qrImgView.bounds.size];
CGSize logoSize=CGSizeMake(30, 30);
self.logoImgView = [self roundCornerWithImage:[UIImage imageNamed:@"logo"] size:logoSize];
_logoImgView.bounds = CGRectMake(0, 0, logoSize.width, logoSize.height);
_logoImgView.center = CGPointMake(CGRectGetWidth(_qrImgView.frame)/2, CGRectGetHeight(_qrImgView.frame)/2);
[_qrImgView addSubview:_logoImgView];
}
- (UIImageView*)roundCornerWithImage:(UIImage*)logoImg size:(CGSize)size
{
//logo
UIImageView *backImage = [[UIImageView alloc] initWithCornerRadiusAdvance:6.0f rectCornerType:UIRectCornerAllCorners];
backImage.frame = CGRectMake(0, 0, size.width, size.height);
backImage.backgroundColor = [UIColor whiteColor];
UIImageView *logImage = [[UIImageView alloc] initWithCornerRadiusAdvance:6.0f rectCornerType:UIRectCornerAllCorners];
logImage.image =logoImg;
CGFloat diff =2;
logImage.frame = CGRectMake(diff, diff, size.width - 2 * diff, size.height - 2 * diff);
[backImage addSubview:logImage];
return backImage;
}
- (void)createQR_color
{
_qrView.hidden = NO;
_tView.hidden = YES;
_qrImgView.image = [LBXScanNative createQRWithString:@"" QRSize:_qrImgView.bounds.size QRColor:[UIColor blueColor] bkColor:[UIColor whiteColor]];
}
//
- (void)createCodeEAN13
{
_qrView.hidden = YES;
_tView.hidden = NO;
[self showError:@"native暂不支持EAN13条形码"];
}
- (void)createCode128
{
_qrView.hidden = YES;
_tView.hidden = NO;
_tImgView.image = [LBXScanNative createBarCodeWithString:@"283657461695996598" QRSize:_qrImgView.bounds.size];
}
- (void)showError:(NSString*)str
{
// [LBXAlertAction showAlertWithTitle:@"提示" msg:str buttonsStatement:@[@"知道了"] chooseBlock:nil];
}
@end

View File

@ -0,0 +1,97 @@
//
// LBXScanBaseViewController.h
//
//
#import <UIKit/UIKit.h>
#import "LBXScanTypes.h"
#import "LBXScanView.h"
#import "LBXScanNative.h"
@interface LBXScanBaseViewController : UIViewController<UIImagePickerControllerDelegate,UINavigationControllerDelegate>
#pragma mark ---- 需要初始化参数 ------
/**
@brief
*/
@property (nonatomic, assign) BOOL isNeedScanImage;
/**
@brief
*/
@property (nonatomic, assign) BOOL continuous;
/**
@brief
*/
@property(nonatomic,assign) BOOL isOpenInterestRect;
/**
, ...
*/
@property (nonatomic, copy) NSString *cameraInvokeMsg;
//相机预览
@property (nonatomic, strong) UIView *cameraPreView;
/**
*
*/
@property (nonatomic, strong) LBXScanViewStyle *style;
//default AVCaptureVideoOrientationPortrait
@property (nonatomic, assign) AVCaptureVideoOrientation orientation;
/**
@brief ,
*/
@property (nonatomic,strong) LBXScanView* qRScanView;
/// 首次加载
@property (nonatomic, assign) BOOL firstLoad;
//条码识别位置标示
@property (nonatomic, strong) UIView *codeFlagView;
@property (nonatomic, strong) NSArray<CALayer*> *layers;
/**
@brief
*/
@property(nonatomic,strong) UIImage* scanImage;
/**
@brief
*/
@property(nonatomic,assign)BOOL isOpenFlash;
//继承者实现
- (void)reStartDevice;
- (void)scanResultWithArray:(NSArray<LBXScanResult*>*)array;
- (void)resetCodeFlagView;
///截取UIImage指定区域图片
- (UIImage *)imageByCroppingWithSrcImage:(UIImage*)srcImg cropRect:(CGRect)cropRect;
- (void)requestCameraPemissionWithResult:(void(^)( BOOL granted))completion;
+ (void)authorizePhotoPermissionWithCompletion:(void(^)(BOOL granted,BOOL firstTime))completion;
- (BOOL)isLandScape;
- (AVCaptureVideoOrientation)videoOrientation;
@end

View File

@ -0,0 +1,557 @@
//
// LBXScanBaseViewController.m
//
#import "LBXScanBaseViewController.h"
#import <AssetsLibrary/AssetsLibrary.h>
#import <Photos/Photos.h>
#import "ScanResultViewController.h"
//#import "LBXToast.h"
@interface LBXScanBaseViewController ()
@end
@implementation LBXScanBaseViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
if ([self respondsToSelector:@selector(setEdgesForExtendedLayout:)]) {
self.edgesForExtendedLayout = UIRectEdgeNone;
}
self.view.backgroundColor = [UIColor blackColor];
#if TARGET_IPHONE_SIMULATOR
self.view.backgroundColor = [UIColor whiteColor];
#else
#endif
self.firstLoad = YES;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(statusBarOrientationChanged:) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter]removeObserver:self];
self.firstLoad = NO;
}
- (void)statusBarOrientationChanged:(NSNotification*)notification
{
}
#pragma mark-
- (void)scanResultWithArray:(NSArray<LBXScanResult*>*)array
{
if (!array || array.count < 1)
{
NSLog(@"失败失败了。。。。");
NSLog(@"失败失败了。。。。");
NSLog(@"失败失败了。。。。");
if (!_continuous) {
[self reStartDevice];
}
return;
}
//ZXing2
// for (LBXScanResult *result in array) {
//
// NSLog(@"scanResult:%@",result.strScanned);
// }
LBXScanResult *scanResult = array[0];
NSString*strResult = scanResult.strScanned;
if (_continuous) {
if (strResult) {
// [LBXToast showToastWithMessage:strResult];
}
return;
}
if (!strResult) {
[self reStartDevice];
return;
}
[self.qRScanView stopScanAnimation];
self.scanImage = scanResult.imgScanned;
//TODO:
//...
//TODO:
//ZXing
if (!self.isOpenInterestRect && self.cameraPreView && !CGRectEqualToRect(CGRectZero, scanResult.bounds) ) {
CGFloat centerX = scanResult.bounds.origin.x + scanResult.bounds.size.width / 2;
CGFloat centerY = scanResult.bounds.origin.y + scanResult.bounds.size.height / 2;
//
[self signCodeWithCenterX:centerX centerY:centerY];
//
[self didDetectCodes:scanResult.bounds corner:scanResult.corners];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.8 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// dispatch_async(dispatch_get_main_queue(), ^{
[self showNextVCWithScanResult:scanResult];
// });
});
}
else
{
[self showNextVCWithScanResult:scanResult];
}
}
-(UIImage *)getImageFromLayer:(CALayer *)layer size:(CGSize)size
{
UIGraphicsBeginImageContextWithOptions(size, YES, [[UIScreen mainScreen]scale]);
[layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
- (CGPoint)pointForCorner:(NSDictionary *)corner {
CGPoint point;
CGPointMakeWithDictionaryRepresentation((CFDictionaryRef)corner, &point);
return point;
}
- (void)handCorners:(NSArray<NSDictionary *> *)corners bounds:(CGRect)bounds
{
CGFloat totalX = 0;
CGFloat totalY = 0;
for (NSDictionary *dic in corners) {
CGPoint pt = [self pointForCorner:dic];
NSLog(@"pt:%@",NSStringFromCGPoint(pt));
totalX += pt.x;
totalY += pt.y;
}
CGFloat averX = totalX / corners.count;
CGFloat averY = totalY / corners.count;
CGFloat minSize = MIN(bounds.size.width , bounds.size.height);
NSLog(@"averx:%f,avery:%f minsize:%f",averX,averY,minSize);
dispatch_async(dispatch_get_main_queue(), ^{
[self signCodeWithCenterX:averX centerY:averY];
});
}
- (void)signCodeWithCenterX:(CGFloat)centerX centerY:(CGFloat)centerY
{
UIView *signView = [[UIView alloc]initWithFrame:CGRectMake(centerX-10, centerY-10, 20, 20)];
[self.cameraPreView addSubview:signView];
signView.backgroundColor = [UIColor redColor];
self.codeFlagView = signView;
}
//
- (void)reStartDevice
{
}
- (void)resetCodeFlagView
{
if (_codeFlagView) {
[_codeFlagView removeFromSuperview];
self.codeFlagView = nil;
}
if (self.layers) {
for (CALayer *layer in self.layers) {
[layer removeFromSuperlayer];
}
self.layers = nil;
}
}
- (UIImage *)imageByCroppingWithSrcImage:(UIImage*)srcImg cropRect:(CGRect)cropRect
{
CGImageRef imageRef = srcImg.CGImage;
CGImageRef imagePartRef = CGImageCreateWithImageInRect(imageRef, cropRect);
UIImage *cropImage = [UIImage imageWithCGImage:imagePartRef];
CGImageRelease(imagePartRef);
return cropImage;
}
- (void)showNextVCWithScanResult:(LBXScanResult*)strResult
{
if (_continuous) {
}else
{
ScanResultViewController *vc = [ScanResultViewController new];
vc.imgScan = strResult.imgScanned;
vc.strScan = strResult.strScanned;
vc.strCodeType = strResult.strBarCodeType;
[self.navigationController pushViewController:vc animated:YES];
//
[self resetCodeFlagView];
}
}
#pragma mark-
- (void)didDetectCodes:(CGRect)bounds corner:(NSArray<NSDictionary*>*)corners
{
AVCaptureVideoPreviewLayer * preview = nil;
for (CALayer *layer in [self.cameraPreView.layer sublayers]) {
if ( [layer isKindOfClass:[AVCaptureVideoPreviewLayer class]]) {
preview = (AVCaptureVideoPreviewLayer*)layer;
}
}
NSArray *layers = nil;
if (!layers) {
layers = @[[self makeBoundsLayer],[self makeCornersLayer]];
[preview addSublayer:layers[0]];
[preview addSublayer:layers[1]];
}
CAShapeLayer *boundsLayer = layers[0];
boundsLayer.path = [self bezierPathForBounds:bounds].CGPath;
//CGPathRefpath
if (corners) {
CAShapeLayer *cornersLayer = layers[1];
cornersLayer.path = [self bezierPathForCorners:corners].CGPath;
//cornersLayerCGPath
}
self.layers = layers;
}
- (UIBezierPath *)bezierPathForBounds:(CGRect)bounds {
// boundsUIBezierPath
return [UIBezierPath bezierPathWithRect:bounds];
}
- (CAShapeLayer *)makeBoundsLayer {
//CAShapeLayer CALayerBezier
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.strokeColor = [UIColor colorWithRed:0.96f green:0.75f blue:0.06f alpha:1.0f].CGColor;
shapeLayer.fillColor = nil;
shapeLayer.lineWidth = 4.0f;
return shapeLayer;
}
- (CAShapeLayer *)makeCornersLayer {
CAShapeLayer *cornersLayer = [CAShapeLayer layer];
cornersLayer.lineWidth = 2.0f;
cornersLayer.strokeColor = [UIColor colorWithRed:0.172 green:0.671 blue:0.428 alpha:1.0].CGColor;
cornersLayer.fillColor = [UIColor colorWithRed:0.190 green:0.753 blue:0.489 alpha:0.5].CGColor;
return cornersLayer;;
}
- (UIBezierPath *)bezierPathForCorners:(NSArray *)corners {
UIBezierPath *path = [UIBezierPath bezierPath];
for (int i = 0; i < corners.count; i ++) {
CGPoint point = [self pointForCorner:corners[i]];
//CGPoint
if (i == 0) {
[path moveToPoint:point];
} else {
[path addLineToPoint:point];
}
}
[path closePath];
return path;
}
#pragma mark-
//
- (void)recognizeImageWithImage:(UIImage*)image
{
}
-(void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
__block UIImage* image = [info objectForKey:UIImagePickerControllerEditedImage];
if (!image){
image = [info objectForKey:UIImagePickerControllerOriginalImage];
}
[picker dismissViewControllerAnimated:YES completion:^{
[self recognizeImageWithImage:image];
}];
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
NSLog(@"cancel");
[picker dismissViewControllerAnimated:YES completion:nil];
}
#pragma mark-
- (void)requestCameraPemissionWithResult:(void(^)( BOOL granted))completion
{
if ([AVCaptureDevice respondsToSelector:@selector(authorizationStatusForMediaType:)])
{
AVAuthorizationStatus permission =
[AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
switch (permission) {
case AVAuthorizationStatusAuthorized:
completion(YES);
break;
case AVAuthorizationStatusDenied:
case AVAuthorizationStatusRestricted:
completion(NO);
break;
case AVAuthorizationStatusNotDetermined:
{
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo
completionHandler:^(BOOL granted) {
dispatch_async(dispatch_get_main_queue(), ^{
if (granted) {
completion(true);
} else {
completion(false);
}
});
}];
}
break;
}
}
}
+ (void)authorizePhotoPermissionWithCompletion:(void(^)(BOOL granted,BOOL firstTime))completion
{
if (@available(iOS 8.0, *)) {
PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];
switch (status) {
case PHAuthorizationStatusAuthorized:
{
if (completion) {
completion(YES,NO);
}
}
break;
case PHAuthorizationStatusRestricted:
case PHAuthorizationStatusDenied:
{
if (completion) {
completion(NO,NO);
}
}
break;
case PHAuthorizationStatusNotDetermined:
{
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
if (completion) {
dispatch_async(dispatch_get_main_queue(), ^{
completion(status == PHAuthorizationStatusAuthorized,YES);
});
}
}];
}
break;
default:
{
if (completion) {
completion(NO,NO);
}
}
break;
}
}else{
ALAuthorizationStatus status = [ALAssetsLibrary authorizationStatus];
switch (status) {
case ALAuthorizationStatusAuthorized:
{
if (completion) {
completion(YES, NO);
}
}
break;
case ALAuthorizationStatusNotDetermined:
{
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library enumerateGroupsWithTypes:ALAssetsGroupAll
usingBlock:^(ALAssetsGroup *assetGroup, BOOL *stop) {
if (*stop) {
if (completion) {
dispatch_async(dispatch_get_main_queue(), ^{
completion(YES, NO);
});
}
} else {
*stop = YES;
}
}
failureBlock:^(NSError *error) {
if (completion) {
dispatch_async(dispatch_get_main_queue(), ^{
completion(NO, YES);
});
}
}];
} break;
case ALAuthorizationStatusRestricted:
case ALAuthorizationStatusDenied:
{
if (completion) {
completion(NO, NO);
}
}
break;
}
}
}
- (BOOL)isLandScape
{
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
BOOL landScape = NO;
switch (orientation) {
case UIDeviceOrientationPortrait: {
landScape = NO;
}
break;
case UIDeviceOrientationLandscapeLeft: {
landScape = YES;
}
break;
case UIDeviceOrientationLandscapeRight: {
landScape = YES;
}
break;
case UIDeviceOrientationPortraitUpsideDown: {
landScape = NO;
}
break;
default:
break;
}
return landScape;
}
- (AVCaptureVideoOrientation)videoOrientation
{
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
switch (orientation) {
case UIDeviceOrientationPortrait: {
return AVCaptureVideoOrientationPortrait;
}
break;
case UIDeviceOrientationLandscapeRight : {
return AVCaptureVideoOrientationLandscapeLeft;
}
break;
case UIDeviceOrientationLandscapeLeft: {
return AVCaptureVideoOrientationLandscapeRight;
}
break;
case UIDeviceOrientationPortraitUpsideDown: {
return AVCaptureVideoOrientationPortraitUpsideDown;
}
break;
default:
return AVCaptureVideoOrientationPortrait;
break;
}
return AVCaptureVideoOrientationPortrait;
}
@end

View File

@ -0,0 +1,27 @@
//
// LBXScanLineAnimation.h
//
// github:https://github.com/MxABC/LBXScan
//
#import <UIKit/UIKit.h>
@interface LBXScanLineAnimation : UIImageView
/**
* 线
*
* @param animationRect parentView中得区域
* @param parentView UIView
* @param image 线
*/
- (void)startAnimatingWithRect:(CGRect)animationRect InView:(UIView*)parentView Image:(UIImage*)image;
/**
*
*/
- (void)stopAnimating;
@end

View File

@ -0,0 +1,155 @@
//
// LBXScanLineAnimation.m
//
//
#import "LBXScanLineAnimation.h"
@interface LBXScanLineAnimation()
{
int num;
BOOL down;
NSTimer * timer;
BOOL isAnimationing;
}
@property (nonatomic,assign) CGRect animationRect;
@end
@implementation LBXScanLineAnimation
- (void)stepAnimation
{
if (!isAnimationing) {
return;
}
CGFloat leftx = _animationRect.origin.x + 5;
CGFloat width = _animationRect.size.width - 10;
self.frame = CGRectMake(leftx, _animationRect.origin.y + 8, width, 8);
self.alpha = 0.0;
self.hidden = NO;
[UIView animateWithDuration:0.5 animations:^{
self.alpha = 1.0;
} completion:^(BOOL finished)
{
}];
[UIView animateWithDuration:3 animations:^{
CGFloat leftx = self.animationRect.origin.x + 5;
CGFloat width = self.animationRect.size.width - 10;
self.frame = CGRectMake(leftx, self.animationRect.origin.y + self.animationRect.size.height - 8, width, 4);
} completion:^(BOOL finished)
{
self.hidden = YES;
[self performSelector:@selector(stepAnimation) withObject:nil afterDelay:0.3];
}];
}
- (void)startAnimatingWithRect:(CGRect)animationRect InView:(UIView *)parentView Image:(UIImage*)image
{
if (isAnimationing) {
return;
}
isAnimationing = YES;
self.animationRect = animationRect;
down = YES;
num =0;
CGFloat centery = CGRectGetMinY(animationRect) + CGRectGetHeight(animationRect)/2;
CGFloat leftx = animationRect.origin.x + 5;
CGFloat width = animationRect.size.width - 10;
self.frame = CGRectMake(leftx, centery+2*num, width, 2);
self.image = image;
[parentView addSubview:self];
[self startAnimating_UIViewAnimation];
// [self startAnimating_NSTimer];
}
- (void)startAnimating_UIViewAnimation
{
[self stepAnimation];
}
- (void)startAnimating_NSTimer
{
timer = [NSTimer scheduledTimerWithTimeInterval:.02 target:self selector:@selector(scanLineAnimation) userInfo:nil repeats:YES];
}
-(void)scanLineAnimation
{
CGFloat centery = CGRectGetMinY(_animationRect) + CGRectGetHeight(_animationRect)/2;
CGFloat leftx = _animationRect.origin.x + 5;
CGFloat width = _animationRect.size.width - 10;
if (down)
{
num++;
self.frame = CGRectMake(leftx, centery+2*num, width, 2);
if (centery+2*num > (CGRectGetMinY(_animationRect) + CGRectGetHeight(_animationRect) - 5 ) )
{
down = NO;
}
}
else {
num --;
self.frame = CGRectMake(leftx, centery+2*num, width, 2);
if (centery+2*num < (CGRectGetMinY(_animationRect) + 5 ) )
{
down = YES;
}
}
}
- (void)dealloc
{
[self stopAnimating];
}
- (void)stopAnimating
{
if (isAnimationing) {
isAnimationing = NO;
if (timer) {
[timer invalidate];
timer = nil;
}
[self removeFromSuperview];
}
[NSObject cancelPreviousPerformRequestsWithTarget:self];
}
@end

View File

@ -0,0 +1,48 @@
//
// QQStyleQRScanViewController.h
//
// github:https://github.com/MxABC/LBXScan
//
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>
#import "LBXScanBaseViewController.h"
@interface LBXScanNativeViewController : LBXScanBaseViewController
#pragma mark ----- 扫码使用的库对象 -------
/**
@brief
*/
@property (nonatomic,strong) LBXScanNative* scanObj;
/*
AVMetadataObject.h ,
AVMetadataObjectTypeQRCode QR二维码
AVMetadataObjectTypeCode128Code
AVMetadataObjectTypeCode93Code 93
AVMetadataObjectTypeEAN13Code EAN13条码
AVMetadataObjectTypeITF14Code native效果比较差ZXing
*/
//虽然接口是支持可以输入多个码制,但是同时多个效果不理想
@property (nonatomic, strong) NSArray<NSString*> *listScanTypes;
//打开相册
- (void)openLocalPhoto:(BOOL)allowsEditing;
//开关闪光灯
- (void)openOrCloseFlash;
//关闭扫描
- (void)stopScan;
@end

View File

@ -0,0 +1,282 @@
//
//
//
#import "LBXScanNativeViewController.h"
@interface LBXScanNativeViewController ()
//@property (nonatomic, strong) UIView *videoView;
@end
@implementation LBXScanNativeViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
if ([self respondsToSelector:@selector(setEdgesForExtendedLayout:)]) {
self.edgesForExtendedLayout = UIRectEdgeNone;
}
self.view.backgroundColor = [UIColor blackColor];
self.title = [NSString stringWithFormat:@"native 支持横竖屏切换 - %@",self.continuous ? @"连续扫码" : @"不连续扫码"];
[self drawScanView];
[self requestCameraPemissionWithResult:^(BOOL granted) {
if (granted) {
[self startScan];
}
}];
}
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
CGRect rect = self.view.frame;
rect.origin = CGPointMake(0, 0);
self.qRScanView.frame = rect;
self.cameraPreView.frame = self.view.bounds;
if (_scanObj) {
[_scanObj setVideoLayerframe:self.cameraPreView.frame];
}
[self.qRScanView stopScanAnimation];
[self.qRScanView startScanAnimation];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if (!self.firstLoad) {
[self reStartDevice];
}
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[self stopScan];
[self.qRScanView stopScanAnimation];
}
//
- (void)drawScanView
{
if (!self.qRScanView)
{
self.qRScanView = [[LBXScanView alloc]initWithFrame:self.view.bounds style:self.style];
[self.view insertSubview:self.qRScanView atIndex:1];
}
if (!self.cameraInvokeMsg) {
self.cameraInvokeMsg = NSLocalizedString(@"wating...", nil);
}
}
- (void)reStartDevice
{
[self refreshLandScape];
[self.qRScanView startDeviceReadyingWithText:self.cameraInvokeMsg];
_scanObj.orientation = [self videoOrientation];
[_scanObj startScan];
}
//
- (void)startScan
{
if (!self.cameraPreView) {
CGRect frame = self.view.bounds;
UIView *videoView = [[UIView alloc]initWithFrame:frame];
videoView.backgroundColor = [UIColor clearColor];
[self.view insertSubview:videoView atIndex:0];
self.cameraPreView = videoView;
}
__weak __typeof(self) weakSelf = self;
if (!_scanObj )
{
CGRect cropRect = CGRectZero;
if (self.isOpenInterestRect) {
//
cropRect = [LBXScanView getScanRectWithPreView:self.view style:self.style];
}
self.scanObj = [[LBXScanNative alloc]initWithPreView:self.cameraPreView ObjectType:self.listScanTypes cropRect:cropRect videoMaxScale:^(CGFloat maxScale) {
[weakSelf setVideoMaxScale:maxScale];
} success:^(NSArray<LBXScanResult *> *array) {
[weakSelf handScanNative:array];
}];
[_scanObj setNeedCaptureImage:self.isNeedScanImage];
//
_scanObj.needCodePosion = YES;
_scanObj.continuous = self.continuous;
}
_scanObj.onStarted = ^{
[weakSelf.qRScanView stopDeviceReadying];
[weakSelf.qRScanView startScanAnimation];
};
//
_scanObj.orientation = [self videoOrientation];
[self.qRScanView startDeviceReadyingWithText:self.cameraInvokeMsg];
#if TARGET_OS_SIMULATOR
#else
[_scanObj startScan];
#endif
self.view.backgroundColor = [UIColor clearColor];
}
- (void)handScanNative:(NSArray<LBXScanResult *> *)array
{
[self scanResultWithArray:array];
}
- (void)setVideoMaxScale:(CGFloat)maxScale
{
}
- (void)stopScan
{
[_scanObj stopScan];
}
//
- (void)openOrCloseFlash
{
[_scanObj changeTorch];
self.isOpenFlash =!self.isOpenFlash;
}
#pragma mark-
- (void)refreshLandScape
{
if ([self isLandScape]) {
self.style.centerUpOffset = 20;
CGFloat w = [UIScreen mainScreen].bounds.size.width;
CGFloat h = [UIScreen mainScreen].bounds.size.height;
CGFloat max = MAX(w, h);
CGFloat min = MIN(w, h);
CGFloat scanRetangeH = min / 3;
self.style.xScanRetangleOffset = max / 2 - scanRetangeH / 2;
}
else
{
self.style.centerUpOffset = 40;
self.style.xScanRetangleOffset = 60;
}
self.qRScanView.viewStyle = self.style;
[self.qRScanView setNeedsDisplay];
}
- (void)statusBarOrientationChanged:(NSNotification*)notification
{
[self refreshLandScape];
if ([self respondsToSelector:@selector(setEdgesForExtendedLayout:)]) {
self.edgesForExtendedLayout = UIRectEdgeNone;
}
if (_scanObj) {
_scanObj.orientation = [self videoOrientation];
}
[self.qRScanView stopScanAnimation];
[self.qRScanView startScanAnimation];
}
#pragma mark --
/*!
*
*/
- (void)openLocalPhoto:(BOOL)allowsEditing
{
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
picker.delegate = self;
//
picker.allowsEditing = allowsEditing;
[self presentViewController:picker animated:YES completion:nil];
}
- (void)recognizeImageWithImage:(UIImage*)image
{
__weak __typeof(self) weakSelf = self;
if (@available(iOS 8.0, *)) {
[LBXScanNative recognizeImage:image success:^(NSArray<LBXScanResult *> *array) {
[weakSelf scanResultWithArray:array];
}];
}
}
@end

View File

@ -0,0 +1,27 @@
//
// LBXScanLineAnimation.h
//
// github:https://github.com/MxABC/LBXScan
//
#import <UIKit/UIKit.h>
@interface LBXScanNetAnimation :UIView
/**
*
*
* @param animationRect parentView中得区域
* @param parentView UIView
* @param image 线
*/
- (void)startAnimatingWithRect:(CGRect)animationRect InView:(UIView*)parentView Image:(UIImage*)image;
/**
*
*/
- (void)stopAnimating;
@end

View File

@ -0,0 +1,95 @@
//
// LBXScanLineAnimation.m
//
//
#import "LBXScanNetAnimation.h"
@interface LBXScanNetAnimation()
{
BOOL isAnimationing;
}
@property (nonatomic,assign) CGRect animationRect;
@property (nonatomic,strong) UIImageView *scanImageView;
@end
@implementation LBXScanNetAnimation
- (instancetype)init{
self = [super init];
if (self) {
self.clipsToBounds = YES;
[self addSubview:self.scanImageView];
}
return self;
}
- (UIImageView *)scanImageView{
if (!_scanImageView) {
_scanImageView = [[UIImageView alloc] init];
}
return _scanImageView;
}
- (void)stepAnimation
{
if (!isAnimationing) {
return;
}
self.frame = _animationRect;
CGFloat scanNetImageViewW = self.frame.size.width;
CGFloat scanNetImageH = self.frame.size.height;
self.alpha = 0.5;
_scanImageView.frame = CGRectMake(0, -scanNetImageH, scanNetImageViewW, scanNetImageH);
[UIView animateWithDuration:1.4 animations:^{
self.alpha = 1.0;
self.scanImageView.frame = CGRectMake(0, scanNetImageViewW-scanNetImageH, scanNetImageViewW, scanNetImageH);
} completion:^(BOOL finished)
{
[self performSelector:@selector(stepAnimation) withObject:nil afterDelay:0.3];
}];
}
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
[self performSelector:@selector(stepAnimation) withObject:nil afterDelay:0.3];
}
- (void)startAnimatingWithRect:(CGRect)animationRect InView:(UIView *)parentView Image:(UIImage*)image
{
[self.scanImageView setImage:image];
self.animationRect = animationRect;
[parentView addSubview:self];
self.hidden = NO;
isAnimationing = YES;
[self stepAnimation];
}
- (void)dealloc
{
[self stopAnimating];
}
- (void)stopAnimating
{
self.hidden = YES;
isAnimationing = NO;
[NSObject cancelPreviousPerformRequestsWithTarget:self];
}
@end

View File

@ -0,0 +1,19 @@
//
// LBXScanVideoZoomView.h
// testSlider
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface LBXScanVideoZoomView : UIView
/**
@brief
*/
@property (nonatomic, copy,nullable) void (^block)(float value);
- (void)setMaximunValue:(CGFloat)value;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,126 @@
//
// LBXScanVideoZoomView.m
// testSlider
//
//
#import "LBXScanVideoZoomView.h"
@interface LBXScanVideoZoomView()
@property (nonatomic, strong) UISlider *slider;
@end
@implementation LBXScanVideoZoomView
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
UIColor *colorLine = [UIColor whiteColor];
CGColorRef color = colorLine.CGColor;
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSetStrokeColorWithColor(ctx, color);
CGContextSetLineWidth(ctx, 2.0);
CGFloat borderDiff = 20;
CGFloat w = borderDiff/2;
CGFloat diff = 5;
//
CGContextMoveToPoint(ctx, diff, CGRectGetHeight(self.frame)/2);
CGContextAddLineToPoint(ctx, diff + w, CGRectGetHeight(self.frame)/2);
//
//
CGFloat rx = CGRectGetWidth(self.frame) - borderDiff + diff;
CGContextMoveToPoint(ctx, rx, CGRectGetHeight(self.frame)/2);
CGContextAddLineToPoint(ctx, rx + w, CGRectGetHeight(self.frame)/2);
//
CGFloat hDiff = CGRectGetHeight(self.frame)/2 - w/2;
CGContextMoveToPoint(ctx, rx+w/2 , hDiff);
CGContextAddLineToPoint(ctx, rx+w/2, CGRectGetHeight(self.frame)-hDiff);
CGContextStrokePath(ctx);
}
- (UIImage *) toImage:(UIColor*)color size:(CGSize)size
{
CGRect rect=CGRectMake(0.0f, 0.0f, size.width, size.height);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [color CGColor]);
CGContextFillRect(context, rect);
UIImage *theImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return theImage;
}
- (id)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
}
self.backgroundColor = [UIColor colorWithRed:10 green:10 blue:10 alpha:0.2];
[self.slider setThumbImage:[self toImage:[UIColor whiteColor] size:CGSizeMake(3, 12)] forState:UIControlStateNormal];
self.slider.minimumTrackTintColor = [UIColor whiteColor];
self.slider.maximumTrackTintColor = [UIColor colorWithRed:146/255.0 green:146/255.0 blue:146/255.0 alpha:1.0];
[self.slider addTarget:self action:@selector(sliderValueChange) forControlEvents:UIControlEventValueChanged];
self.layer.masksToBounds = YES;
self.layer.cornerRadius = 8.0;
return self;
}
- (void)sliderValueChange
{
NSLog(@"%f",self.slider.value);
if (_block) {
_block(self.slider.value);
}
}
//- (void)addTarget:(nullable id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents;
- (UISlider*)slider
{
if (!_slider) {
_slider = [[UISlider alloc]init];
[self addSubview:_slider];
_slider.minimumValue = 1.0;
_slider.maximumValue = 50.0;
}
return _slider;
}
- (void)setMaximunValue:(CGFloat)value
{
self.slider.maximumValue = value;
}
- (void)layoutSubviews
{
[super layoutSubviews];
CGFloat borderDiff = 20;
_slider.bounds = CGRectMake(0, 0, CGRectGetWidth(self.frame)-borderDiff*2, CGRectGetHeight(self.frame));
_slider.center = CGPointMake(CGRectGetWidth(self.frame)/2, CGRectGetHeight(self.frame)/2);
}
@end

View File

@ -0,0 +1,73 @@
//
// LBXScanView.h
//
// github:https://github.com/MxABC/LBXScan
//
#import <UIKit/UIKit.h>
#import "LBXScanLineAnimation.h"
#import "LBXScanNetAnimation.h"
#import "LBXScanViewStyle.h"
#define LBXScan_Define_UI
/**
*/
@interface LBXScanView : UIView
//扫码区域各种参数
@property (nonatomic, strong) LBXScanViewStyle* viewStyle;
/**
@brief
@param frame
@param style
@return instancetype
*/
-(id)initWithFrame:(CGRect)frame style:(LBXScanViewStyle*)style;
/**
*
*/
- (void)startDeviceReadyingWithText:(NSString*)text;
/**
*
*/
- (void)stopDeviceReadying;
/**
*
*/
- (void)startScanAnimation;
/**
*
*/
- (void)stopScanAnimation;
//
/**
@brief Native扫码识别兴趣区域
@param view UIView
@param style
@return
*/
+ (CGRect)getScanRectWithPreView:(UIView*)view style:(LBXScanViewStyle*)style;
/**
ZXing库扫码识别兴趣区域
@param view
@param style
@return
*/
+ (CGRect)getZXingScanRectWithPreView:(UIView*)view style:(LBXScanViewStyle*)style;
@end

View File

@ -0,0 +1,519 @@
//
// LBXScanView.m
//
//
#import "LBXScanView.h"
NS_ASSUME_NONNULL_BEGIN
@interface LBXScanView()
//
@property (nonatomic,assign)CGRect scanRetangleRect;
//线
@property (nonatomic,strong,nullable)LBXScanLineAnimation *scanLineAnimation;
//
@property (nonatomic,strong,nullable)LBXScanNetAnimation *scanNetAnimation;
//线
@property (nonatomic,strong,nullable)UIImageView *scanLineStill;
/**
@brief
*/
@property(nonatomic,strong,nullable)UIActivityIndicatorView* activityView;
/**
@brief
*/
@property(nonatomic,strong,nullable)UILabel *labelReadying;
@end
NS_ASSUME_NONNULL_END
@implementation LBXScanView
-(id)initWithFrame:(CGRect)frame style:(LBXScanViewStyle*)style
{
if (self = [super initWithFrame:frame])
{
self.viewStyle = style;
self.backgroundColor = [UIColor clearColor];
}
return self;
}
- (void)drawRect:(CGRect)rect
{
[self drawScanRect];
}
- (void)startDeviceReadyingWithText:(NSString*)text
{
int XRetangleLeft = _viewStyle.xScanRetangleOffset;
CGSize sizeRetangle = CGSizeMake(self.frame.size.width - XRetangleLeft*2, self.frame.size.width - XRetangleLeft*2);
if (!_viewStyle.isNeedShowRetangle) {
CGFloat w = sizeRetangle.width;
CGFloat h = w / _viewStyle.whRatio;
NSInteger hInt = (NSInteger)h;
h = hInt;
sizeRetangle = CGSizeMake(w, h);
}
//Y
CGFloat YMinRetangle = self.frame.size.height / 2.0 - sizeRetangle.height/2.0 - _viewStyle.centerUpOffset;
//
if (!_activityView)
{
self.activityView = [[UIActivityIndicatorView alloc]init];
[_activityView setActivityIndicatorViewStyle:UIActivityIndicatorViewStyleWhiteLarge];
self.labelReadying = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, sizeRetangle.width, 30)];
_labelReadying.backgroundColor = [UIColor clearColor];
_labelReadying.textColor = [UIColor whiteColor];
_labelReadying.font = [UIFont systemFontOfSize:18.];
_labelReadying.text = text;
[_labelReadying sizeToFit];
CGRect frame = _labelReadying.frame;
CGPoint centerPt = CGPointMake(self.frame.size.width/2 + 20, YMinRetangle + sizeRetangle.height/2);
_labelReadying.bounds = CGRectMake(0, 0, frame.size.width,30);
_labelReadying.center = centerPt;
_activityView.bounds = CGRectMake(0, 0, 30, 30);
if (text)
_activityView.center = CGPointMake(centerPt.x - frame.size.width/2 - 24 , _labelReadying.center.y);
else
_activityView.center = CGPointMake(self.frame.size.width/2 , _labelReadying.center.y);
[self addSubview:_activityView];
[self addSubview:_labelReadying];
[_activityView startAnimating];
}
}
- (void)layoutSubviews
{
[super layoutSubviews];
if (_labelReadying && _activityView) {
int XRetangleLeft = _viewStyle.xScanRetangleOffset;
CGSize sizeRetangle = CGSizeMake(self.frame.size.width - XRetangleLeft*2, self.frame.size.width - XRetangleLeft*2);
CGFloat YMinRetangle = self.frame.size.height / 2.0 - sizeRetangle.height/2.0 - _viewStyle.centerUpOffset;
CGRect frame = _labelReadying.frame;
CGPoint centerPt = CGPointMake(self.frame.size.width/2 + 20, YMinRetangle + sizeRetangle.height/2);
_labelReadying.bounds = CGRectMake(0, 0, frame.size.width,30);
_labelReadying.center = centerPt;
_activityView.bounds = CGRectMake(0, 0, 30, 30);
if (_labelReadying.text)
_activityView.center = CGPointMake(centerPt.x - frame.size.width/2 - 24 , _labelReadying.center.y);
else
_activityView.center = CGPointMake(self.frame.size.width/2 , _labelReadying.center.y);
}
}
- (void)stopDeviceReadying
{
if (_activityView) {
[_activityView stopAnimating];
[_activityView removeFromSuperview];
[_labelReadying removeFromSuperview];
self.activityView = nil;
self.labelReadying = nil;
}
}
/**
*
*/
- (void)startScanAnimation
{
[self refreshScanRetangleRect];
switch (_viewStyle.anmiationStyle)
{
case LBXScanViewAnimationStyle_LineMove:
{
//线
if (!_scanLineAnimation)
self.scanLineAnimation = [[LBXScanLineAnimation alloc]init];
[_scanLineAnimation startAnimatingWithRect:_scanRetangleRect
InView:self
Image:_viewStyle.animationImage];
}
break;
case LBXScanViewAnimationStyle_NetGrid:
{
//
if (!_scanNetAnimation)
self.scanNetAnimation = [[LBXScanNetAnimation alloc]init];
[_scanNetAnimation startAnimatingWithRect:_scanRetangleRect
InView:self
Image:_viewStyle.animationImage];
}
break;
case LBXScanViewAnimationStyle_LineStill:
{
if (!_scanLineStill) {
CGRect stillRect = CGRectMake(_scanRetangleRect.origin.x+20,
_scanRetangleRect.origin.y + _scanRetangleRect.size.height/2,
_scanRetangleRect.size.width-40,
2);
_scanLineStill = [[UIImageView alloc]initWithFrame:stillRect];
_scanLineStill.image = _viewStyle.animationImage;
}
[self addSubview:_scanLineStill];
}
default:
break;
}
}
/**
*
*/
- (void)stopScanAnimation
{
if (_scanLineAnimation) {
[_scanLineAnimation stopAnimating];
self.scanLineAnimation = nil;
}
if (_scanNetAnimation) {
[_scanNetAnimation stopAnimating];
self.scanNetAnimation = nil;
}
if (_scanLineStill) {
[_scanLineStill removeFromSuperview];
self.scanLineStill = nil;
}
}
- (void)refreshScanRetangleRect
{
int XRetangleLeft = _viewStyle.xScanRetangleOffset;
CGSize sizeRetangle = CGSizeMake(self.frame.size.width - XRetangleLeft*2, self.frame.size.width - XRetangleLeft*2);
//if (!_viewStyle.isScanRetangelSquare)
if (_viewStyle.whRatio != 1)
{
CGFloat w = sizeRetangle.width;
CGFloat h = w / _viewStyle.whRatio;
NSInteger hInt = (NSInteger)h;
h = hInt;
sizeRetangle = CGSizeMake(w, h);
}
//Y
CGFloat YMinRetangle = self.frame.size.height / 2.0 - sizeRetangle.height/2.0 - _viewStyle.centerUpOffset;
// CGFloat YMaxRetangle = YMinRetangle + sizeRetangle.height;
// CGFloat XRetangleRight = self.frame.size.width - XRetangleLeft;
_scanRetangleRect = CGRectMake(XRetangleLeft, YMinRetangle, sizeRetangle.width, sizeRetangle.height);
}
- (void)drawScanRect
{
int XRetangleLeft = _viewStyle.xScanRetangleOffset;
CGSize sizeRetangle = CGSizeMake(self.frame.size.width - XRetangleLeft*2, self.frame.size.width - XRetangleLeft*2);
//if (!_viewStyle.isScanRetangelSquare)
if (_viewStyle.whRatio != 1)
{
CGFloat w = sizeRetangle.width;
CGFloat h = w / _viewStyle.whRatio;
NSInteger hInt = (NSInteger)h;
h = hInt;
sizeRetangle = CGSizeMake(w, h);
}
//Y
CGFloat YMinRetangle = self.frame.size.height / 2.0 - sizeRetangle.height/2.0 - _viewStyle.centerUpOffset;
CGFloat YMaxRetangle = YMinRetangle + sizeRetangle.height;
CGFloat XRetangleRight = self.frame.size.width - XRetangleLeft;
NSLog(@"frame:%@",NSStringFromCGRect(self.frame));
CGContextRef context = UIGraphicsGetCurrentContext();
//
{
//
const CGFloat *components = CGColorGetComponents(_viewStyle.notRecoginitonArea.CGColor);
CGFloat red_notRecoginitonArea = components[0];
CGFloat green_notRecoginitonArea = components[1];
CGFloat blue_notRecoginitonArea = components[2];
CGFloat alpa_notRecoginitonArea = components[3];
CGContextSetRGBFillColor(context, red_notRecoginitonArea, green_notRecoginitonArea,
blue_notRecoginitonArea, alpa_notRecoginitonArea);
//
//
CGRect rect = CGRectMake(0, 0, self.frame.size.width, YMinRetangle);
CGContextFillRect(context, rect);
//
rect = CGRectMake(0, YMinRetangle, XRetangleLeft,sizeRetangle.height);
CGContextFillRect(context, rect);
//
rect = CGRectMake(XRetangleRight, YMinRetangle, XRetangleLeft,sizeRetangle.height);
CGContextFillRect(context, rect);
//
rect = CGRectMake(0, YMaxRetangle, self.frame.size.width,self.frame.size.height - YMaxRetangle);
CGContextFillRect(context, rect);
//
CGContextStrokePath(context);
}
if (_viewStyle.isNeedShowRetangle)
{
//()
CGContextSetStrokeColorWithColor(context, _viewStyle.colorRetangleLine.CGColor);
CGContextSetLineWidth(context, 1);
CGContextAddRect(context, CGRectMake(XRetangleLeft, YMinRetangle, sizeRetangle.width, sizeRetangle.height));
//CGContextMoveToPoint(context, XRetangleLeft, YMinRetangle);
//CGContextAddLineToPoint(context, XRetangleLeft+sizeRetangle.width, YMinRetangle);
CGContextStrokePath(context);
}
_scanRetangleRect = CGRectMake(XRetangleLeft, YMinRetangle, sizeRetangle.width, sizeRetangle.height);
//4
//
int wAngle = _viewStyle.photoframeAngleW;
int hAngle = _viewStyle.photoframeAngleH;
//4 线
CGFloat linewidthAngle = _viewStyle.photoframeLineW;// 64
//
CGFloat diffAngle = 0.0f;
//diffAngle = linewidthAngle / 2; //4
//diffAngle = linewidthAngle/2; //4 线4
//diffAngle = 0;//
switch (_viewStyle.photoframeAngleStyle)
{
case LBXScanViewPhotoframeAngleStyle_Outer:
{
diffAngle = linewidthAngle/3;//4
}
break;
case LBXScanViewPhotoframeAngleStyle_On:
{
diffAngle = 0;
}
break;
case LBXScanViewPhotoframeAngleStyle_Inner:
{
diffAngle = -_viewStyle.photoframeLineW/2;
}
break;
default:
{
diffAngle = linewidthAngle/3;
}
break;
}
CGContextSetStrokeColorWithColor(context, _viewStyle.colorAngle.CGColor);
CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 1.0);
// Draw them with a 2.0 stroke width so they are a bit more visible.
CGContextSetLineWidth(context, linewidthAngle);
//
CGFloat leftX = XRetangleLeft - diffAngle;
CGFloat topY = YMinRetangle - diffAngle;
CGFloat rightX = XRetangleRight + diffAngle;
CGFloat bottomY = YMaxRetangle + diffAngle;
//线
CGContextMoveToPoint(context, leftX-linewidthAngle/2, topY);
CGContextAddLineToPoint(context, leftX + wAngle, topY);
//线
CGContextMoveToPoint(context, leftX, topY-linewidthAngle/2);
CGContextAddLineToPoint(context, leftX, topY+hAngle);
//线
CGContextMoveToPoint(context, leftX-linewidthAngle/2, bottomY);
CGContextAddLineToPoint(context, leftX + wAngle, bottomY);
//线
CGContextMoveToPoint(context, leftX, bottomY+linewidthAngle/2);
CGContextAddLineToPoint(context, leftX, bottomY - hAngle);
//线
CGContextMoveToPoint(context, rightX+linewidthAngle/2, topY);
CGContextAddLineToPoint(context, rightX - wAngle, topY);
//线
CGContextMoveToPoint(context, rightX, topY-linewidthAngle/2);
CGContextAddLineToPoint(context, rightX, topY + hAngle);
//线
CGContextMoveToPoint(context, rightX+linewidthAngle/2, bottomY);
CGContextAddLineToPoint(context, rightX - wAngle, bottomY);
//线
CGContextMoveToPoint(context, rightX, bottomY+linewidthAngle/2);
CGContextAddLineToPoint(context, rightX, bottomY - hAngle);
CGContextStrokePath(context);
}
//
+ (CGRect)getScanRectWithPreView:(UIView*)view style:(LBXScanViewStyle*)style
{
int XRetangleLeft = style.xScanRetangleOffset;
CGSize sizeRetangle = CGSizeMake(view.frame.size.width - XRetangleLeft*2, view.frame.size.width - XRetangleLeft*2);
if (style.whRatio != 1)
{
CGFloat w = sizeRetangle.width;
CGFloat h = w / style.whRatio;
NSInteger hInt = (NSInteger)h;
h = hInt;
sizeRetangle = CGSizeMake(w, h);
}
//Y
CGFloat YMinRetangle = view.frame.size.height / 2.0 - sizeRetangle.height/2.0 - style.centerUpOffset;
//
CGRect cropRect = CGRectMake(XRetangleLeft, YMinRetangle, sizeRetangle.width, sizeRetangle.height);
//
CGRect rectOfInterest;
//ref:http://www.cocoachina.com/ios/20141225/10763.html
CGSize size = view.bounds.size;
CGFloat p1 = size.height/size.width;
CGFloat p2 = 1920./1080.; //使1080p
if (p1 < p2) {
CGFloat fixHeight = size.width * 1920. / 1080.;
CGFloat fixPadding = (fixHeight - size.height)/2;
rectOfInterest = CGRectMake((cropRect.origin.y + fixPadding)/fixHeight,
cropRect.origin.x/size.width,
cropRect.size.height/fixHeight,
cropRect.size.width/size.width);
} else {
CGFloat fixWidth = size.height * 1080. / 1920.;
CGFloat fixPadding = (fixWidth - size.width)/2;
rectOfInterest = CGRectMake(cropRect.origin.y/size.height,
(cropRect.origin.x + fixPadding)/fixWidth,
cropRect.size.height/size.height,
cropRect.size.width/fixWidth);
}
return rectOfInterest;
}
//
+ (CGRect)getZXingScanRectWithPreView:(UIView*)view style:(LBXScanViewStyle*)style
{
int XRetangleLeft = style.xScanRetangleOffset;
CGSize sizeRetangle = CGSizeMake(view.frame.size.width - XRetangleLeft*2, view.frame.size.width - XRetangleLeft*2);
if (style.whRatio != 1)
{
CGFloat w = sizeRetangle.width;
CGFloat h = w / style.whRatio;
NSInteger hInt = (NSInteger)h;
h = hInt;
sizeRetangle = CGSizeMake(w, h);
}
//Y
CGFloat YMinRetangle = view.frame.size.height / 2.0 - sizeRetangle.height/2.0 - style.centerUpOffset;
XRetangleLeft = XRetangleLeft/view.frame.size.width * 1080;
YMinRetangle = YMinRetangle / view.frame.size.height * 1920;
CGFloat width = sizeRetangle.width / view.frame.size.width * 1080;
CGFloat height = sizeRetangle.height / view.frame.size.height * 1920;
//
CGRect cropRect = CGRectMake(XRetangleLeft, YMinRetangle, width,height);
return cropRect;
}
@end

View File

@ -0,0 +1,174 @@
//
// QQStyleQRScanViewController.h
//
// github:https://github.com/MxABC/LBXScan
//
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import "LBXScanTypes.h"
//UI
#ifdef LBXScan_Define_UI
#import "LBXScanView.h"
#endif
#ifdef LBXScan_Define_Native
#import "LBXScanNative.h" //原生扫码封装
#endif
#ifdef LBXScan_Define_ZXing
#import "ZXingWrapper.h" //ZXing扫码封装
#endif
#ifdef LBXScan_Define_ZBar
#import "ZBarSDK.h"
#import "LBXZBarWrapper.h"//ZBar扫码封装
#endif
typedef NS_ENUM(NSInteger, SCANLIBRARYTYPE) {
SLT_Native,
SLT_ZXing,
SLT_ZBar
};
// @[@"QRCode",@"BarCode93",@"BarCode128",@"BarCodeITF",@"EAN13"];
typedef NS_ENUM(NSInteger, SCANCODETYPE) {
SCT_QRCode, //QR二维码
SCT_BarCode93,
SCT_BarCode128,//支付条形码(支付宝、微信支付条形码)
SCT_BarCodeITF,//燃气回执联 条形码?
SCT_BarEAN13 //一般用做商品码
};
/**
delegate,override方法scanResultWithArray即可
*/
@protocol LBXScanViewControllerDelegate <NSObject>
@optional
- (void)scanResultWithArray:(NSArray<LBXScanResult*>*)array;
@end
@interface LBXScanViewController : UIViewController<UIImagePickerControllerDelegate,UINavigationControllerDelegate>
#pragma mark ---- 需要初始化参数 ------
//当前选择的扫码库
@property (nonatomic, assign) SCANLIBRARYTYPE libraryType;
//
/**
- ZXing暂不支持类型选择
*/
@property (nonatomic, assign) SCANCODETYPE scanCodeType;
//扫码结果委托另外一种方案是通过继承本控制器override方法scanResultWithArray即可
@property (nonatomic, weak) id<LBXScanViewControllerDelegate> delegate;
/**
@brief
*/
@property (nonatomic, assign) BOOL isNeedScanImage;
/**
@brief ZBar暂不支持
*/
@property(nonatomic,assign) BOOL isOpenInterestRect;
/**
, ...
*/
@property (nonatomic, copy) NSString *cameraInvokeMsg;
/**
*
*/
#ifdef LBXScan_Define_UI
@property (nonatomic, strong) LBXScanViewStyle *style;
#endif
#pragma mark ----- 扫码使用的库对象 -------
#ifdef LBXScan_Define_Native
/**
@brief
*/
@property (nonatomic,strong) LBXScanNative* scanObj;
#endif
#ifdef LBXScan_Define_ZXing
/**
ZXing扫码对象
*/
@property (nonatomic, strong) ZXingWrapper *zxingObj;
#endif
#ifdef LBXScan_Define_ZBar
/**
ZBar扫码对象
*/
@property (nonatomic, strong) LBXZBarWrapper *zbarObj;
#endif
#pragma mark - 扫码界面效果及提示等
/**
@brief ,
*/
#ifdef LBXScan_Define_UI
@property (nonatomic,strong) LBXScanView* qRScanView;
#endif
/**
@brief
*/
@property(nonatomic,strong) UIImage* scanImage;
/**
@brief
*/
@property(nonatomic,assign)BOOL isOpenFlash;
//打开相册
- (void)openLocalPhoto:(BOOL)allowsEditing;
//开关闪光灯
- (void)openOrCloseFlash;
//启动扫描
- (void)reStartDevice;
//关闭扫描
- (void)stopScan;
@end

View File

@ -0,0 +1,596 @@
//
//
//
#import "LBXScanViewController.h"
#import <AssetsLibrary/AssetsLibrary.h>
#import <Photos/Photos.h>
@interface LBXScanViewController ()
@end
@implementation LBXScanViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
if ([self respondsToSelector:@selector(setEdgesForExtendedLayout:)]) {
self.edgesForExtendedLayout = UIRectEdgeNone;
}
self.view.backgroundColor = [UIColor blackColor];
switch (_libraryType) {
case SLT_Native:
self.title = @"native";
break;
case SLT_ZXing:
self.title = @"ZXing";
break;
case SLT_ZBar:
self.title = @"ZBar";
break;
default:
break;
}
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self drawScanView];
[self requestCameraPemissionWithResult:^(BOOL granted) {
if (granted) {
//
[self performSelector:@selector(startScan) withObject:nil afterDelay:0.3];
}else{
#ifdef LBXScan_Define_UI
[self.qRScanView stopDeviceReadying];
#endif
}
}];
}
//
- (void)drawScanView
{
#ifdef LBXScan_Define_UI
if (!_qRScanView)
{
CGRect rect = self.view.frame;
rect.origin = CGPointMake(0, 0);
self.qRScanView = [[LBXScanView alloc]initWithFrame:rect style:_style];
[self.view addSubview:_qRScanView];
}
if (!_cameraInvokeMsg) {
// _cameraInvokeMsg = NSLocalizedString(@"wating...", nil);
}
[_qRScanView startDeviceReadyingWithText:_cameraInvokeMsg];
#endif
}
- (void)reStartDevice
{
switch (_libraryType) {
case SLT_Native:
{
#ifdef LBXScan_Define_Native
[_scanObj startScan];
#endif
}
break;
case SLT_ZXing:
{
#ifdef LBXScan_Define_ZXing
[_zxingObj start];
#endif
}
break;
case SLT_ZBar:
{
#ifdef LBXScan_Define_ZBar
[_zbarObj start];
#endif
}
break;
default:
break;
}
}
//
- (void)startScan
{
UIView *videoView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.view.frame), CGRectGetHeight(self.view.frame))];
videoView.backgroundColor = [UIColor clearColor];
[self.view insertSubview:videoView atIndex:0];
__weak __typeof(self) weakSelf = self;
switch (_libraryType) {
case SLT_Native:
{
#ifdef LBXScan_Define_Native
if (!_scanObj )
{
CGRect cropRect = CGRectZero;
if (_isOpenInterestRect) {
//
cropRect = [LBXScanView getScanRectWithPreView:self.view style:_style];
}
NSString *strCode = AVMetadataObjectTypeQRCode;
if (_scanCodeType != SCT_BarCodeITF ) {
strCode = [self nativeCodeWithType:_scanCodeType];
}
//AVMetadataObjectTypeITF14Code ,
self.scanObj = [[LBXScanNative alloc]initWithPreView:videoView ObjectType:@[strCode] cropRect:cropRect success:^(NSArray<LBXScanResult *> *array) {
[weakSelf scanResultWithArray:array];
}];
[_scanObj setNeedCaptureImage:_isNeedScanImage];
}
[_scanObj startScan];
#endif
}
break;
case SLT_ZXing:
{
#ifdef LBXScan_Define_ZXing
if (!_zxingObj) {
__weak __typeof(self) weakSelf = self;
self.zxingObj = [[ZXingWrapper alloc]initWithPreView:videoView block:^(ZXBarcodeFormat barcodeFormat, NSString *str, UIImage *scanImg) {
LBXScanResult *result = [[LBXScanResult alloc]init];
result.strScanned = str;
result.imgScanned = scanImg;
result.strBarCodeType = [weakSelf convertZXBarcodeFormat:barcodeFormat];
[weakSelf scanResultWithArray:@[result]];
}];
if (_isOpenInterestRect) {
//
CGRect cropRect = [LBXScanView getZXingScanRectWithPreView:videoView style:_style];
[_zxingObj setScanRect:cropRect];
}
}
[_zxingObj start];
#endif
}
break;
case SLT_ZBar:
{
#ifdef LBXScan_Define_ZBar
if (!_zbarObj) {
self.zbarObj = [[LBXZBarWrapper alloc]initWithPreView:videoView barCodeType:[self zbarTypeWithScanType:_scanCodeType] block:^(NSArray<LBXZbarResult *> *result) {
//使
LBXZbarResult *firstObj = result[0];
LBXScanResult *scanResult = [[LBXScanResult alloc]init];
scanResult.strScanned = firstObj.strScanned;
scanResult.imgScanned = firstObj.imgScanned;
scanResult.strBarCodeType = [LBXZBarWrapper convertFormat2String:firstObj.format];
[weakSelf scanResultWithArray:@[scanResult]];
}];
}
[_zbarObj start];
#endif
}
break;
default:
break;
}
#ifdef LBXScan_Define_UI
[_qRScanView stopDeviceReadying];
[_qRScanView startScanAnimation];
#endif
self.view.backgroundColor = [UIColor clearColor];
}
#ifdef LBXScan_Define_ZBar
- (zbar_symbol_type_t)zbarTypeWithScanType:(SCANCODETYPE)type
{
//test only ZBAR_I25 effective,why
return ZBAR_I25;
// switch (type) {
// case SCT_QRCode:
// return ZBAR_QRCODE;
// break;
// case SCT_BarCode93:
// return ZBAR_CODE93;
// break;
// case SCT_BarCode128:
// return ZBAR_CODE128;
// break;
// case SCT_BarEAN13:
// return ZBAR_EAN13;
// break;
//
// default:
// break;
// }
//
// return (zbar_symbol_type_t)type;
}
#endif
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[NSObject cancelPreviousPerformRequestsWithTarget:self];
[self stopScan];
#ifdef LBXScan_Define_UI
[_qRScanView stopScanAnimation];
#endif
}
- (void)stopScan
{
switch (_libraryType) {
case SLT_Native:
{
#ifdef LBXScan_Define_Native
[_scanObj stopScan];
#endif
}
break;
case SLT_ZXing:
{
#ifdef LBXScan_Define_ZXing
[_zxingObj stop];
#endif
}
break;
case SLT_ZBar:
{
#ifdef LBXScan_Define_ZBar
[_zbarObj stop];
#endif
}
break;
default:
break;
}
}
#pragma mark -
- (void)scanResultWithArray:(NSArray<LBXScanResult*>*)array
{
//
if (_delegate && array && array.count > 0) {
[_delegate scanResultWithArray:array];
}
//LBXScanViewController
}
//
- (void)openOrCloseFlash
{
switch (_libraryType) {
case SLT_Native:
{
#ifdef LBXScan_Define_Native
[_scanObj changeTorch];
#endif
}
break;
case SLT_ZXing:
{
#ifdef LBXScan_Define_ZXing
[_zxingObj openOrCloseTorch];
#endif
}
break;
case SLT_ZBar:
{
#ifdef LBXScan_Define_ZBar
[_zbarObj openOrCloseFlash];
#endif
}
break;
default:
break;
}
self.isOpenFlash =!self.isOpenFlash;
}
#pragma mark --
/*!
*
*/
- (void)openLocalPhoto:(BOOL)allowsEditing
{
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
picker.delegate = self;
//
picker.allowsEditing = allowsEditing;
[self presentViewController:picker animated:YES completion:nil];
}
//
-(void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
[picker dismissViewControllerAnimated:YES completion:nil];
__block UIImage* image = [info objectForKey:UIImagePickerControllerEditedImage];
if (!image){
image = [info objectForKey:UIImagePickerControllerOriginalImage];
}
__weak __typeof(self) weakSelf = self;
switch (_libraryType) {
case SLT_Native:
{
#ifdef LBXScan_Define_Native
if ([[[UIDevice currentDevice]systemVersion]floatValue] >= 8.0)
{
[LBXScanNative recognizeImage:image success:^(NSArray<LBXScanResult *> *array) {
[weakSelf scanResultWithArray:array];
}];
}
else
{
[self showError:@"native低于ios8.0系统不支持识别图片条码"];
}
#endif
}
break;
case SLT_ZXing:
{
#ifdef LBXScan_Define_ZXing
[ZXingWrapper recognizeImage:image block:^(ZXBarcodeFormat barcodeFormat, NSString *str) {
LBXScanResult *result = [[LBXScanResult alloc]init];
result.strScanned = str;
result.imgScanned = image;
result.strBarCodeType = [self convertZXBarcodeFormat:barcodeFormat];
[weakSelf scanResultWithArray:@[result]];
}];
#endif
}
break;
case SLT_ZBar:
{
#ifdef LBXScan_Define_ZBar
[LBXZBarWrapper recognizeImage:image block:^(NSArray<LBXZbarResult *> *result) {
//使
LBXZbarResult *firstObj = result[0];
LBXScanResult *scanResult = [[LBXScanResult alloc]init];
scanResult.strScanned = firstObj.strScanned;
scanResult.imgScanned = firstObj.imgScanned;
scanResult.strBarCodeType = [LBXZBarWrapper convertFormat2String:firstObj.format];
[weakSelf scanResultWithArray:@[scanResult]];
}];
#endif
}
break;
default:
break;
}
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
NSLog(@"cancel");
[picker dismissViewControllerAnimated:YES completion:nil];
}
#ifdef LBXScan_Define_ZXing
- (NSString*)convertZXBarcodeFormat:(ZXBarcodeFormat)barCodeFormat
{
NSString *strAVMetadataObjectType = nil;
switch (barCodeFormat) {
case kBarcodeFormatQRCode:
strAVMetadataObjectType = AVMetadataObjectTypeQRCode;
break;
case kBarcodeFormatEan13:
strAVMetadataObjectType = AVMetadataObjectTypeEAN13Code;
break;
case kBarcodeFormatEan8:
strAVMetadataObjectType = AVMetadataObjectTypeEAN8Code;
break;
case kBarcodeFormatPDF417:
strAVMetadataObjectType = AVMetadataObjectTypePDF417Code;
break;
case kBarcodeFormatAztec:
strAVMetadataObjectType = AVMetadataObjectTypeAztecCode;
break;
case kBarcodeFormatCode39:
strAVMetadataObjectType = AVMetadataObjectTypeCode39Code;
break;
case kBarcodeFormatCode93:
strAVMetadataObjectType = AVMetadataObjectTypeCode93Code;
break;
case kBarcodeFormatCode128:
strAVMetadataObjectType = AVMetadataObjectTypeCode128Code;
break;
case kBarcodeFormatDataMatrix:
strAVMetadataObjectType = AVMetadataObjectTypeDataMatrixCode;
break;
case kBarcodeFormatITF:
strAVMetadataObjectType = AVMetadataObjectTypeITF14Code;
break;
case kBarcodeFormatRSS14:
break;
case kBarcodeFormatRSSExpanded:
break;
case kBarcodeFormatUPCA:
break;
case kBarcodeFormatUPCE:
strAVMetadataObjectType = AVMetadataObjectTypeUPCECode;
break;
default:
break;
}
return strAVMetadataObjectType;
}
#endif
- (NSString*)nativeCodeWithType:(SCANCODETYPE)type
{
switch (type) {
case SCT_QRCode:
return AVMetadataObjectTypeQRCode;
break;
case SCT_BarCode93:
return AVMetadataObjectTypeCode93Code;
break;
case SCT_BarCode128:
return AVMetadataObjectTypeCode128Code;
break;
case SCT_BarCodeITF:
return @"ITF条码:only ZXing支持";
break;
case SCT_BarEAN13:
return AVMetadataObjectTypeEAN13Code;
break;
default:
return AVMetadataObjectTypeQRCode;
break;
}
}
- (void)showError:(NSString*)str
{
}
- (void)requestCameraPemissionWithResult:(void(^)( BOOL granted))completion
{
if ([AVCaptureDevice respondsToSelector:@selector(authorizationStatusForMediaType:)])
{
AVAuthorizationStatus permission =
[AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
switch (permission) {
case AVAuthorizationStatusAuthorized:
completion(YES);
break;
case AVAuthorizationStatusDenied:
case AVAuthorizationStatusRestricted:
completion(NO);
break;
case AVAuthorizationStatusNotDetermined:
{
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo
completionHandler:^(BOOL granted) {
dispatch_async(dispatch_get_main_queue(), ^{
if (granted) {
completion(true);
} else {
completion(false);
}
});
}];
}
break;
}
}
}
+ (BOOL)photoPermission
{
if (@available(iOS 8.0, *)) {
PHAuthorizationStatus authorStatus = [PHPhotoLibrary authorizationStatus];
if ( authorStatus == PHAuthorizationStatusDenied ) {
return NO;
}
}else{
ALAuthorizationStatus author = [ALAssetsLibrary authorizationStatus];
if ( author == ALAuthorizationStatusDenied ) {
return NO;
}
return YES;
}
return NO;
}
@end

View File

@ -0,0 +1,119 @@
//
// LBXScanViewStyle.h
//
// github:https://github.com/MxABC/LBXScan
// Created by lbxia on 15/11/15.
// Copyright © 2015年 lbxia. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
/**
*/
typedef NS_ENUM(NSInteger,LBXScanViewAnimationStyle)
{
LBXScanViewAnimationStyle_LineMove, //线条上下移动
LBXScanViewAnimationStyle_NetGrid,//网格
LBXScanViewAnimationStyle_LineStill,//线条停止在扫码区域中央
LBXScanViewAnimationStyle_None //无动画
};
/**
4
*/
typedef NS_ENUM(NSInteger, LBXScanViewPhotoframeAngleStyle)
{
LBXScanViewPhotoframeAngleStyle_Inner,//内嵌,一般不显示矩形框情况下
LBXScanViewPhotoframeAngleStyle_Outer,//外嵌,包围在矩形框的4个角
LBXScanViewPhotoframeAngleStyle_On //在矩形框的4个角上覆盖
};
NS_ASSUME_NONNULL_BEGIN
@interface LBXScanViewStyle : NSObject
#pragma mark -中心位置矩形框
/**
@brief YES
*/
@property (nonatomic, assign) BOOL isNeedShowRetangle;
/**
*
*/
@property (nonatomic, assign) CGFloat whRatio;
/**
@brief ()0< 0 , >0
*/
@property (nonatomic, assign) CGFloat centerUpOffset;
/**
* ()60
*/
@property (nonatomic, assign) CGFloat xScanRetangleOffset;
/**
@brief 线
*/
@property (nonatomic, strong) UIColor *colorRetangleLine;
#pragma mark -矩形框(扫码区域)周围4个角
/**
@brief 4
*/
@property (nonatomic, assign) LBXScanViewPhotoframeAngleStyle photoframeAngleStyle;
//4个角的颜色
@property (nonatomic, strong) UIColor* colorAngle;
//扫码区域4个角的宽度和高度
@property (nonatomic, assign) CGFloat photoframeAngleW;
@property (nonatomic, assign) CGFloat photoframeAngleH;
/**
@brief 4线,684
*/
@property (nonatomic, assign) CGFloat photoframeLineW;
#pragma mark --动画效果
/**
@brief :线
*/
@property (nonatomic, assign) LBXScanViewAnimationStyle anmiationStyle;
/**
* 线nil
*/
@property (nonatomic,strong,nullable) UIImage *animationImage;
#pragma mark -非识别区域颜色,默认 RGBA (0,0,0,0.5)
/**
must be create by [UIColor colorWithRed: green: blue: alpha:]
*/
@property (nonatomic, strong) UIColor *notRecoginitonArea;
/// 生成路径
/// @param name CodeScan.bundle内的文件名称
+ (NSString*)imagePathWithName:(NSString*)name;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,52 @@
//
// LBXScanViewStyle.m
//
//
// Created by lbxia on 15/11/15.
// Copyright © 2015 lbxia. All rights reserved.
//
#import "LBXScanViewStyle.h"
@implementation LBXScanViewStyle
- (id)init
{
if (self = [super init])
{
_isNeedShowRetangle = YES;
_whRatio = 1.0;
_colorRetangleLine = [UIColor whiteColor];
_centerUpOffset = 44;
_xScanRetangleOffset = 60;
_anmiationStyle = LBXScanViewAnimationStyle_LineMove;
_photoframeAngleStyle = LBXScanViewPhotoframeAngleStyle_Outer;
_colorAngle = [UIColor colorWithRed:0. green:167./255. blue:231./255. alpha:1.0];
_notRecoginitonArea = [UIColor colorWithRed:0. green:.0 blue:.0 alpha:.5];
_photoframeAngleW = 24;
_photoframeAngleH = 24;
_photoframeLineW = 7;
}
return self;
}
+ (NSString*)imagePathWithName:(NSString*)name
{
NSString *bundlePath = [[NSBundle bundleForClass:self.class] pathForResource:@"CodeScan" ofType:@"bundle"];
NSString* path = [NSString stringWithFormat:@"%@/%@",bundlePath, name];
return path;
}
@end

View File

@ -0,0 +1,38 @@
//
// SubLBXScanViewController.h
//
// github:https://github.com/MxABC/LBXScan
//
#import "LBXScanNativeViewController.h"
#pragma mark
//继承LBXScanViewController,在界面上绘制想要的按钮,提示语等
@interface QQScanNativeViewController : LBXScanNativeViewController
/**
@brief
*/
@property (nonatomic, strong) UILabel *topTitle;
#pragma mark --增加拉近/远视频界面
@property (nonatomic, assign) BOOL isVideoZoom;
#pragma mark - 底部几个功能:开启闪光灯、相册、我的二维码
//底部显示的功能项
@property (nonatomic, strong) UIView *bottomItemsView;
//相册
@property (nonatomic, strong) UIButton *btnPhoto;
//闪光灯
@property (nonatomic, strong) UIButton *btnFlash;
//我的二维码
@property (nonatomic, strong) UIButton *btnMyQR;
@end

View File

@ -0,0 +1,290 @@
//
//
//
#import "QQScanNativeViewController.h"
#import "CreateBarCodeViewController.h"
#import "ScanResultViewController.h"
#import "LBXScanVideoZoomView.h"
#import "LBXPermission.h"
#import "LBXPermissionSetting.h"
@interface QQScanNativeViewController ()
@property (nonatomic, strong) LBXScanVideoZoomView *zoomView;
@property (nonatomic, assign) CGFloat maxVideoScale;
@end
@implementation QQScanNativeViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
if ([self respondsToSelector:@selector(setEdgesForExtendedLayout:)]) {
self.edgesForExtendedLayout = UIRectEdgeNone;
}
self.view.backgroundColor = [UIColor blackColor];
//
self.isNeedScanImage = YES;
}
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
if (_topTitle) {
_topTitle.bounds = CGRectMake(0, 0, 145, 60);
_topTitle.center = CGPointMake(CGRectGetWidth(self.view.frame)/2, 50);
}
if (_bottomItemsView) {
CGRect frame = CGRectMake(0, CGRectGetMaxY(self.view.bounds)-100,
CGRectGetWidth(self.view.bounds), 100);
self.bottomItemsView.frame = frame;
CGSize size = CGSizeMake(65, 87);
_btnFlash.bounds = CGRectMake(0, 0, size.width, size.height);
_btnFlash.center = CGPointMake(CGRectGetWidth(_bottomItemsView.frame)/2, CGRectGetHeight(_bottomItemsView.frame)/2);
_btnPhoto.bounds = _btnFlash.bounds;
_btnPhoto.center = CGPointMake(CGRectGetWidth(_bottomItemsView.frame)/4, CGRectGetHeight(_bottomItemsView.frame)/2);
_btnMyQR.bounds = _btnFlash.bounds;
_btnMyQR.center = CGPointMake(CGRectGetWidth(_bottomItemsView.frame) * 3/4, CGRectGetHeight(_bottomItemsView.frame)/2);
}
if (_zoomView) {
CGRect frame = self.view.frame;
int XRetangleLeft = self.style.xScanRetangleOffset;
CGSize sizeRetangle = CGSizeMake(frame.size.width - XRetangleLeft*2, frame.size.width - XRetangleLeft*2);
if (self.style.whRatio != 1)
{
CGFloat w = sizeRetangle.width;
CGFloat h = w / self.style.whRatio;
NSInteger hInt = (NSInteger)h;
h = hInt;
sizeRetangle = CGSizeMake(w, h);
}
//Y
CGFloat YMinRetangle = frame.size.height / 2.0 - sizeRetangle.height/2.0 - self.style.centerUpOffset;
CGFloat YMaxRetangle = YMinRetangle + sizeRetangle.height;
CGFloat zoomw = sizeRetangle.width + 40;
_zoomView.frame = CGRectMake((CGRectGetWidth(self.view.frame)-zoomw)/2, YMaxRetangle + 40, zoomw, 18);
}
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self drawBottomItems];
[self drawTitle];
}
//
- (void)drawTitle
{
if (!_topTitle)
{
self.topTitle = [[UILabel alloc]init];
_topTitle.bounds = CGRectMake(0, 0, 145, 60);
_topTitle.center = CGPointMake(CGRectGetWidth(self.view.frame)/2, 50);
//3.5inch iphone
if ([UIScreen mainScreen].bounds.size.height <= 568 )
{
_topTitle.center = CGPointMake(CGRectGetWidth(self.view.frame)/2, 38);
_topTitle.font = [UIFont systemFontOfSize:14];
}
_topTitle.textAlignment = NSTextAlignmentCenter;
_topTitle.numberOfLines = 0;
_topTitle.text = @"将取景框对准二维码即可自动扫描";
_topTitle.textColor = [UIColor whiteColor];
// [self.view addSubview:_topTitle];
[self.view insertSubview:_topTitle atIndex:3];
}
}
- (void)cameraInitOver
{
if (self.isVideoZoom) {
[self zoomView];
}
}
- (void)setVideoMaxScale:(CGFloat)maxScale
{
if (_isVideoZoom) {
self.maxVideoScale = maxScale;
dispatch_async(dispatch_get_main_queue(), ^{
[self zoomView];
});
}
}
- (LBXScanVideoZoomView*)zoomView
{
if (!_zoomView)
{
CGRect frame = self.view.frame;
int XRetangleLeft = self.style.xScanRetangleOffset;
CGSize sizeRetangle = CGSizeMake(frame.size.width - XRetangleLeft*2, frame.size.width - XRetangleLeft*2);
if (self.style.whRatio != 1)
{
CGFloat w = sizeRetangle.width;
CGFloat h = w / self.style.whRatio;
NSInteger hInt = (NSInteger)h;
h = hInt;
sizeRetangle = CGSizeMake(w, h);
}
//Y
CGFloat YMinRetangle = frame.size.height / 2.0 - sizeRetangle.height/2.0 - self.style.centerUpOffset;
CGFloat YMaxRetangle = YMinRetangle + sizeRetangle.height;
CGFloat zoomw = sizeRetangle.width + 40;
_zoomView = [[LBXScanVideoZoomView alloc]initWithFrame:CGRectMake((CGRectGetWidth(self.view.frame)-zoomw)/2, YMaxRetangle + 40, zoomw, 18)];
[_zoomView setMaximunValue:self.maxVideoScale/2];
__weak __typeof(self) weakSelf = self;
_zoomView.block= ^(float value)
{
[weakSelf.scanObj setVideoScale:value];
};
[self.view insertSubview:_zoomView atIndex:3];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap)];
[self.view addGestureRecognizer:tap];
}
return _zoomView;
}
- (void)tap
{
_zoomView.hidden = !_zoomView.hidden;
}
- (void)drawBottomItems
{
if (_bottomItemsView) {
return;
}
CGRect frame = CGRectMake(0, CGRectGetMaxY(self.view.bounds)-100,
CGRectGetWidth(self.view.bounds), 100);
self.bottomItemsView = [[UIView alloc]initWithFrame:frame];
_bottomItemsView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.6];
#if TARGET_IPHONE_SIMULATOR
_bottomItemsView.backgroundColor = [UIColor colorWithRed:1 green:1 blue:1 alpha:0.5];
#endif
[self.view insertSubview:_bottomItemsView atIndex:3];
CGSize size = CGSizeMake(65, 87);
self.btnFlash = [[UIButton alloc]init];
_btnFlash.bounds = CGRectMake(0, 0, size.width, size.height);
_btnFlash.center = CGPointMake(CGRectGetWidth(_bottomItemsView.frame)/2, CGRectGetHeight(_bottomItemsView.frame)/2);
[_btnFlash setImage:[UIImage imageNamed:@"CodeScan.bundle/qrcode_scan_btn_flash_nor"] forState:UIControlStateNormal];
[_btnFlash addTarget:self action:@selector(openOrCloseFlash) forControlEvents:UIControlEventTouchUpInside];
self.btnPhoto = [[UIButton alloc]init];
_btnPhoto.bounds = _btnFlash.bounds;
_btnPhoto.center = CGPointMake(CGRectGetWidth(_bottomItemsView.frame)/4, CGRectGetHeight(_bottomItemsView.frame)/2);
[_btnPhoto setImage:[UIImage imageNamed:@"CodeScan.bundle/qrcode_scan_btn_photo_nor"] forState:UIControlStateNormal];
[_btnPhoto setImage:[UIImage imageNamed:@"CodeScan.bundle/qrcode_scan_btn_photo_down"] forState:UIControlStateHighlighted];
[_btnPhoto addTarget:self action:@selector(openPhoto) forControlEvents:UIControlEventTouchUpInside];
self.btnMyQR = [[UIButton alloc]init];
_btnMyQR.bounds = _btnFlash.bounds;
_btnMyQR.center = CGPointMake(CGRectGetWidth(_bottomItemsView.frame) * 3/4, CGRectGetHeight(_bottomItemsView.frame)/2);
[_btnMyQR setImage:[UIImage imageNamed:@"CodeScan.bundle/qrcode_scan_btn_myqrcode_nor"] forState:UIControlStateNormal];
[_btnMyQR setImage:[UIImage imageNamed:@"CodeScan.bundle/qrcode_scan_btn_myqrcode_down"] forState:UIControlStateHighlighted];
[_btnMyQR addTarget:self action:@selector(myQRCode) forControlEvents:UIControlEventTouchUpInside];
[_bottomItemsView addSubview:_btnFlash];
[_bottomItemsView addSubview:_btnPhoto];
[_bottomItemsView addSubview:_btnMyQR];
}
#pragma mark -
//
- (void)openPhoto
{
__weak __typeof(self) weakSelf = self;
[LBXPermission authorizeWithType:LBXPermissionType_Photos completion:^(BOOL granted, BOOL firstTime) {
if (granted) {
[weakSelf openLocalPhoto:NO];
}
else if (!firstTime )
{
[LBXPermissionSetting showAlertToDislayPrivacySettingWithTitle:@"提示" msg:@"没有相册权限,是否前往设置" cancel:@"取消" setting:@"设置"];
}
}];
}
//
- (void)openOrCloseFlash
{
[super openOrCloseFlash];
if (self.isOpenFlash)
{
[_btnFlash setImage:[UIImage imageNamed:@"CodeScan.bundle/qrcode_scan_btn_flash_down"] forState:UIControlStateNormal];
}
else
[_btnFlash setImage:[UIImage imageNamed:@"CodeScan.bundle/qrcode_scan_btn_flash_nor"] forState:UIControlStateNormal];
}
#pragma mark -
- (void)myQRCode
{
CreateBarCodeViewController *vc = [CreateBarCodeViewController new];
[self.navigationController pushViewController:vc animated:YES];
}
@end

View File

@ -0,0 +1,16 @@
//
// ScanResultViewController.h
// LBXScanDemo
//
//
#import <UIKit/UIKit.h>
@interface ScanResultViewController : UIViewController
@property (nonatomic, strong) UIImage* imgScan;
@property (nonatomic, copy) NSString* strScan;
@property (nonatomic,copy)NSString *strCodeType;
@end

View File

@ -0,0 +1,43 @@
//
// ScanResultViewController.m
// LBXScanDemo
//
#import "ScanResultViewController.h"
@interface ScanResultViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *scanImg;
@property (weak, nonatomic) IBOutlet UILabel *labelScanText;
@property (weak, nonatomic) IBOutlet UILabel *labelScanCodeType;
@end
@implementation ScanResultViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
if ([self respondsToSelector:@selector(setEdgesForExtendedLayout:)]) {
self.edgesForExtendedLayout = UIRectEdgeNone;
}
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if (!_imgScan) {
_scanImg.backgroundColor = [UIColor grayColor];
}
_scanImg.image = _imgScan;
_labelScanText.text = _strScan;
_labelScanCodeType.text = [NSString stringWithFormat:@"码的类型:%@",_strCodeType];
}
@end

View File

@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="ScanResultViewController">
<connections>
<outlet property="labelScanCodeType" destination="cfU-Y2-7od" id="6zx-aA-Ss7"/>
<outlet property="labelScanText" destination="O9L-0W-wec" id="dvp-ut-CAV"/>
<outlet property="scanImg" destination="3Fg-0B-ez0" id="H7c-ka-lhi"/>
<outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="i5M-Pr-FkT">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="3Fg-0B-ez0">
<rect key="frame" x="67.5" y="15" width="240" height="248"/>
<constraints>
<constraint firstAttribute="width" constant="240" id="DQA-2S-Ytt"/>
<constraint firstAttribute="height" constant="248" id="nRp-Sr-C81"/>
</constraints>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="O9L-0W-wec">
<rect key="frame" x="22" y="342" width="331" height="317"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="码的类型:" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="cfU-Y2-7od">
<rect key="frame" x="57.5" y="283" width="260" height="21"/>
<constraints>
<constraint firstAttribute="width" constant="260" id="B8h-6b-aaQ"/>
<constraint firstAttribute="height" constant="21" id="TEu-B6-VPf"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="O9L-0W-wec" firstAttribute="top" secondItem="cfU-Y2-7od" secondAttribute="bottom" constant="38" id="OIf-1p-ghO"/>
<constraint firstItem="cfU-Y2-7od" firstAttribute="centerX" secondItem="i5M-Pr-FkT" secondAttribute="centerX" id="RB8-3l-N0Y"/>
<constraint firstItem="O9L-0W-wec" firstAttribute="leading" secondItem="i5M-Pr-FkT" secondAttribute="leading" constant="22" id="VBj-gH-cKh"/>
<constraint firstItem="3Fg-0B-ez0" firstAttribute="top" secondItem="i5M-Pr-FkT" secondAttribute="top" constant="15" id="Vys-AE-3EB"/>
<constraint firstAttribute="trailing" secondItem="O9L-0W-wec" secondAttribute="trailing" constant="22" id="Xdw-Ec-kzJ"/>
<constraint firstItem="cfU-Y2-7od" firstAttribute="top" secondItem="3Fg-0B-ez0" secondAttribute="bottom" constant="20" id="Xra-VX-BrP"/>
<constraint firstAttribute="bottom" secondItem="O9L-0W-wec" secondAttribute="bottom" constant="8" id="gBR-n8-CSE"/>
<constraint firstItem="3Fg-0B-ez0" firstAttribute="centerX" secondItem="i5M-Pr-FkT" secondAttribute="centerX" id="n9Y-cz-9w4"/>
</constraints>
<point key="canvasLocation" x="-237" y="10"/>
</view>
</objects>
</document>

View File

@ -0,0 +1,48 @@
//
// DemoListViewModel.h
// LBXScanDemo
//
//
#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>
#import "LBXScanViewStyle.h"
#import "LBXScanViewController.h"
@interface StyleDIY : NSObject
#pragma mark -模仿qq界面
+ (LBXScanViewStyle*)qqStyle;
#pragma mark --模仿支付宝
+ (LBXScanViewStyle*)ZhiFuBaoStyle;
#pragma mark -无边框内嵌4个角
+ (LBXScanViewStyle*)InnerStyle;
#pragma mark -无边框内嵌4个角
+ (LBXScanViewStyle*)weixinStyle;
#pragma mark -框内区域识别
+ (LBXScanViewStyle*)recoCropRect;
#pragma mark -4个角在矩形框线上,网格动画
+ (LBXScanViewStyle*)OnStyle;
#pragma mark -自定义4个角及矩形框颜色
+ (LBXScanViewStyle*)changeColor;
#pragma mark -改变扫码区域位置
+ (LBXScanViewStyle*)changeSize;
#pragma mark -非正方形,可以用在扫码条形码界面
+ (LBXScanViewStyle*)notSquare;
+ (AVCaptureVideoOrientation)videoOrientation;
+ (NSString*)nativeCodeWithType:(SCANCODETYPE)type;
@end

View File

@ -0,0 +1,423 @@
//
// DemoListViewModel.m
// LBXScanDemo
//
// Created by lbxia on 2017/4/1.
// Copyright © 2017 lbx. All rights reserved.
//
#import "StyleDIY.h"
#import <AVFoundation/AVFoundation.h>
@implementation StyleDIY
+ (BOOL)isLandScape
{
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
BOOL landScape = NO;
switch (orientation) {
case UIDeviceOrientationPortrait: {
landScape = NO;
}
break;
case UIDeviceOrientationLandscapeLeft: {
landScape = YES;
}
break;
case UIDeviceOrientationLandscapeRight: {
landScape = YES;
}
break;
case UIDeviceOrientationPortraitUpsideDown: {
landScape = NO;
}
break;
default:
break;
}
return landScape;
}
+ (AVCaptureVideoOrientation)videoOrientation
{
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
switch (orientation) {
case UIDeviceOrientationPortrait: {
return AVCaptureVideoOrientationPortrait;
}
break;
case UIDeviceOrientationLandscapeRight : {
return AVCaptureVideoOrientationLandscapeLeft;
}
break;
case UIDeviceOrientationLandscapeLeft: {
return AVCaptureVideoOrientationLandscapeRight;
}
break;
case UIDeviceOrientationPortraitUpsideDown: {
return AVCaptureVideoOrientationPortraitUpsideDown;
}
break;
default:
return AVCaptureVideoOrientationPortrait;
break;
}
return AVCaptureVideoOrientationPortrait;
}
#pragma mark -仿qq
+ (LBXScanViewStyle*)qqStyle
{
//
//
LBXScanViewStyle *style = [[LBXScanViewStyle alloc]init];
//
style.centerUpOffset = 44;
//4,
style.photoframeAngleStyle = LBXScanViewPhotoframeAngleStyle_Outer;
//4线
style.photoframeLineW = 6;
//4
style.photoframeAngleW = 24;
//4
style.photoframeAngleH = 24;
// --线
style.anmiationStyle = LBXScanViewAnimationStyle_LineMove;
//线
style.animationImage = [UIImage imageNamed:@"CodeScan.bundle/qrcode_scan_light_green"];
style.notRecoginitonArea = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.6];
[self modifyLandScape:style];
return style;
}
#pragma mark --仿
+ (LBXScanViewStyle*)ZhiFuBaoStyle
{
//
LBXScanViewStyle *style = [[LBXScanViewStyle alloc]init];
style.centerUpOffset = 60;
style.xScanRetangleOffset = 30;
if ([UIScreen mainScreen].bounds.size.height <= 480 )
{
//3.5inch
style.centerUpOffset = 40;
style.xScanRetangleOffset = 40;
}
style.photoframeAngleStyle = LBXScanViewPhotoframeAngleStyle_Inner;
style.photoframeLineW = 2.0;
style.photoframeAngleW = 16;
style.photoframeAngleH = 16;
style.isNeedShowRetangle = NO;
style.anmiationStyle = LBXScanViewAnimationStyle_NetGrid;
style.notRecoginitonArea = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.6];
//使
UIImage *imgFullNet = [UIImage imageNamed:@"CodeScan.bundle/qrcode_scan_full_net"];
style.animationImage = imgFullNet;
[self modifyLandScape:style];
return style;
}
+ (void)modifyLandScape:(LBXScanViewStyle*)style
{
if ([self isLandScape]) {
style.centerUpOffset = 20;
CGFloat w = [UIScreen mainScreen].bounds.size.width;
CGFloat h = [UIScreen mainScreen].bounds.size.height;
CGFloat max = MAX(w, h);
CGFloat min = MIN(w, h);
CGFloat scanRetangeH = min / 3;
style.xScanRetangleOffset = max / 2 - scanRetangeH / 2;
}
else
{
style.centerUpOffset = 40;
style.xScanRetangleOffset = 60;
}
}
#pragma mark -4
+ (LBXScanViewStyle*)InnerStyle
{
//
LBXScanViewStyle *style = [[LBXScanViewStyle alloc]init];
style.centerUpOffset = 44;
style.photoframeAngleStyle = LBXScanViewPhotoframeAngleStyle_Inner;
style.photoframeLineW = 3;
style.photoframeAngleW = 18;
style.photoframeAngleH = 18;
style.isNeedShowRetangle = NO;
style.anmiationStyle = LBXScanViewAnimationStyle_LineMove;
//qq线
UIImage *imgLine = [UIImage imageNamed:@"CodeScan.bundle/qrcode_scan_light_green"];
style.animationImage = imgLine;
style.notRecoginitonArea = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.6];
[self modifyLandScape:style];
return style;
}
#pragma mark -4
+ (LBXScanViewStyle*)weixinStyle
{
//
LBXScanViewStyle *style = [[LBXScanViewStyle alloc]init];
style.centerUpOffset = 44;
style.photoframeAngleStyle = LBXScanViewPhotoframeAngleStyle_Inner;
style.photoframeLineW = 2;
style.photoframeAngleW = 18;
style.photoframeAngleH = 18;
style.isNeedShowRetangle = YES;
style.anmiationStyle = LBXScanViewAnimationStyle_LineMove;
style.colorAngle = [UIColor colorWithRed:0./255 green:200./255. blue:20./255. alpha:1.0];
//qq线
UIImage *imgLine = [UIImage imageNamed:@"CodeScan.bundle/qrcode_Scan_weixin_Line"];
style.animationImage = imgLine;
style.notRecoginitonArea = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.6];
[self modifyLandScape:style];
return style;
}
#pragma mark -
+ (LBXScanViewStyle*)recoCropRect
{
//
LBXScanViewStyle *style = [[LBXScanViewStyle alloc]init];
style.centerUpOffset = 44;
style.photoframeAngleStyle = LBXScanViewPhotoframeAngleStyle_On;
style.photoframeLineW = 6;
style.photoframeAngleW = 24;
style.photoframeAngleH = 24;
style.isNeedShowRetangle = YES;
style.anmiationStyle = LBXScanViewAnimationStyle_NetGrid;
//
style.xScanRetangleOffset = 80;
//使
UIImage *imgPartNet = [UIImage imageNamed:@"CodeScan.bundle/qrcode_scan_part_net"];
style.animationImage = imgPartNet;
style.notRecoginitonArea = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.6];
[self modifyLandScape:style];
return style;
}
#pragma mark -4线,
+ (LBXScanViewStyle*)OnStyle
{
//
LBXScanViewStyle *style = [[LBXScanViewStyle alloc]init];
style.centerUpOffset = 44;
style.photoframeAngleStyle = LBXScanViewPhotoframeAngleStyle_On;
style.photoframeLineW = 6;
style.photoframeAngleW = 24;
style.photoframeAngleH = 24;
style.isNeedShowRetangle = YES;
style.anmiationStyle = LBXScanViewAnimationStyle_NetGrid;
//使
UIImage *imgPartNet = [UIImage imageNamed:@"CodeScan.bundle/qrcode_scan_part_net"];
style.animationImage = imgPartNet;
style.notRecoginitonArea = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.6];
[self modifyLandScape:style];
return style;
}
#pragma mark -4
+ (LBXScanViewStyle*)changeColor
{
//
LBXScanViewStyle *style = [[LBXScanViewStyle alloc]init];
style.centerUpOffset = 44;
//4
style.photoframeAngleStyle = LBXScanViewPhotoframeAngleStyle_On;
//4线
style.photoframeLineW = 6;
//4
style.photoframeAngleW = 24;
//4
style.photoframeAngleH = 24;
//
style.isNeedShowRetangle = YES;
//仿
style.anmiationStyle = LBXScanViewAnimationStyle_NetGrid;
style.animationImage = [UIImage imageNamed:@"CodeScan.bundle/qrcode_scan_part_net"];;
//4
style.colorAngle = [UIColor colorWithRed:65./255. green:174./255. blue:57./255. alpha:1.0];
//
style.colorRetangleLine = [UIColor colorWithRed:247/255. green:202./255. blue:15./255. alpha:1.0];
//
style.notRecoginitonArea = [UIColor colorWithRed:247./255. green:202./255 blue:15./255 alpha:0.2];
[self modifyLandScape:style];
return style;
}
#pragma mark -
+ (LBXScanViewStyle*)changeSize
{
//
LBXScanViewStyle *style = [[LBXScanViewStyle alloc]init];
//
style.centerUpOffset = 60;
//
style.xScanRetangleOffset = 100;
style.photoframeAngleStyle = LBXScanViewPhotoframeAngleStyle_On;
style.photoframeLineW = 6;
style.photoframeAngleW = 24;
style.photoframeAngleH = 24;
style.isNeedShowRetangle = YES;
style.anmiationStyle = LBXScanViewAnimationStyle_LineMove;
//qq线
UIImage *imgLine = [UIImage imageNamed:@"CodeScan.bundle/qrcode_scan_light_green"];
style.animationImage = imgLine;
style.notRecoginitonArea = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.6];
[self modifyLandScape:style];
return style;
}
#pragma mark -
+ (UIImage*) createImageWithColor: (UIColor*) color
{
CGRect rect=CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [color CGColor]);
CGContextFillRect(context, rect);
UIImage *theImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return theImage;
}
+ (LBXScanViewStyle*)notSquare
{
//
LBXScanViewStyle *style = [[LBXScanViewStyle alloc]init];
style.centerUpOffset = 44;
style.photoframeAngleStyle = LBXScanViewPhotoframeAngleStyle_Inner;
style.photoframeLineW = 4;
style.photoframeAngleW = 28;
style.photoframeAngleH = 16;
style.isNeedShowRetangle = NO;
style.anmiationStyle = LBXScanViewAnimationStyle_LineStill;
style.animationImage = [[self class] createImageWithColor:[UIColor redColor]];
//
//
style.whRatio = 4.3/2.18;
//
style.xScanRetangleOffset = 30;
style.notRecoginitonArea = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.6];
[self modifyLandScape:style];
return style;
}
+ (NSString*)nativeCodeWithType:(SCANCODETYPE)type
{
switch (type) {
case SCT_QRCode:
return AVMetadataObjectTypeQRCode;
break;
case SCT_BarCode93:
return AVMetadataObjectTypeCode93Code;
break;
case SCT_BarCode128:
return AVMetadataObjectTypeCode128Code;
break;
case SCT_BarCodeITF:
return @"ITF条码:only ZXing支持";
break;
case SCT_BarEAN13:
return AVMetadataObjectTypeEAN13Code;
break;
default:
return AVMetadataObjectTypeQRCode;
break;
}
}
@end

View File

@ -0,0 +1,22 @@
//
// UIImageView+CornerRadius.h
// MyPractise
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface UIImageView (CornerRadius)
- (instancetype)initWithCornerRadiusAdvance:(CGFloat)cornerRadius rectCornerType:(UIRectCorner)rectCornerType;
- (void)zy_cornerRadiusAdvance:(CGFloat)cornerRadius rectCornerType:(UIRectCorner)rectCornerType;
- (instancetype)initWithRoundingRectImageView;
- (void)zy_cornerRadiusRoundingRect;
- (void)zy_attachBorderWidth:(CGFloat)width color:(UIColor *)color;
@end

View File

@ -0,0 +1,248 @@
//
// UIImageView+CornerRadius.m
// MyPractise
//
#import "UIImageView+CornerRadius.h"
#import <objc/runtime.h>
const char kRadius;
const char kRoundingCorners;
const char kIsRounding;
const char kHadAddObserver;
const char kProcessedImage;
const char kBorderWidth;
const char kBorderColor;
@interface UIImageView ()
@property (assign, nonatomic) CGFloat radius;
@property (assign, nonatomic) UIRectCorner roundingCorners;
@property (assign, nonatomic) CGFloat borderWidth;
@property (strong, nonatomic) UIColor *borderColor;
@property (assign, nonatomic) BOOL hadAddObserver;
@property (assign, nonatomic) BOOL isRounding;
@end
@implementation UIImageView (CornerRadius)
/**
* @brief init the Rounding UIImageView, no off-screen-rendered
*/
- (instancetype)initWithRoundingRectImageView {
self = [super init];
if (self) {
[self zy_cornerRadiusRoundingRect];
}
return self;
}
/**
* @brief init the UIImageView with cornerRadius, no off-screen-rendered
*/
- (instancetype)initWithCornerRadiusAdvance:(CGFloat)cornerRadius rectCornerType:(UIRectCorner)rectCornerType {
self = [super init];
if (self) {
[self zy_cornerRadiusAdvance:cornerRadius rectCornerType:rectCornerType];
}
return self;
}
/**
* @brief attach border for UIImageView with width & color
*/
- (void)zy_attachBorderWidth:(CGFloat)width color:(UIColor *)color {
self.borderWidth = width;
self.borderColor = color;
}
#pragma mark - Kernel
/**
* @brief clip the cornerRadius with image, UIImageView must be setFrame before, no off-screen-rendered
*/
- (void)zy_cornerRadiusWithImage:(UIImage *)image cornerRadius:(CGFloat)cornerRadius rectCornerType:(UIRectCorner)rectCornerType {
CGSize size = self.bounds.size;
CGFloat scale = [UIScreen mainScreen].scale;
CGSize cornerRadii = CGSizeMake(cornerRadius, cornerRadius);
UIGraphicsBeginImageContextWithOptions(size, NO, scale);
if (nil == UIGraphicsGetCurrentContext()) {
return;
}
UIBezierPath *cornerPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:rectCornerType cornerRadii:cornerRadii];
[cornerPath addClip];
[image drawInRect:self.bounds];
[self drawBorder:cornerPath];
UIImage *processedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
objc_setAssociatedObject(processedImage, &kProcessedImage, @(1), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
self.image = processedImage;
}
/**
* @brief clip the cornerRadius with image, draw the backgroundColor you want, UIImageView must be setFrame before, no off-screen-rendered, no Color Blended layers
*/
- (void)zy_cornerRadiusWithImage:(UIImage *)image cornerRadius:(CGFloat)cornerRadius rectCornerType:(UIRectCorner)rectCornerType backgroundColor:(UIColor *)backgroundColor {
CGSize size = self.bounds.size;
CGFloat scale = [UIScreen mainScreen].scale;
CGSize cornerRadii = CGSizeMake(cornerRadius, cornerRadius);
UIGraphicsBeginImageContextWithOptions(size, YES, scale);
if (nil == UIGraphicsGetCurrentContext()) {
return;
}
UIBezierPath *cornerPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:rectCornerType cornerRadii:cornerRadii];
UIBezierPath *backgroundRect = [UIBezierPath bezierPathWithRect:self.bounds];
[backgroundColor setFill];
[backgroundRect fill];
[cornerPath addClip];
[image drawInRect:self.bounds];
[self drawBorder:cornerPath];
UIImage *processedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
objc_setAssociatedObject(processedImage, &kProcessedImage, @(1), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
self.image = processedImage;
}
/**
* @brief set cornerRadius for UIImageView, no off-screen-rendered
*/
- (void)zy_cornerRadiusAdvance:(CGFloat)cornerRadius rectCornerType:(UIRectCorner)rectCornerType {
self.radius = cornerRadius;
self.roundingCorners = rectCornerType;
self.isRounding = NO;
if (!self.hadAddObserver) {
[self addObserver:self forKeyPath:@"image" options:NSKeyValueObservingOptionNew context:nil];
self.hadAddObserver = YES;
}
}
/**
* @brief become Rounding UIImageView, no off-screen-rendered
*/
- (void)zy_cornerRadiusRoundingRect {
self.isRounding = YES;
if (!self.hadAddObserver) {
[self addObserver:self forKeyPath:@"image" options:NSKeyValueObservingOptionNew context:nil];
self.hadAddObserver = YES;
}
}
#pragma mark - Private
- (void)drawBorder:(UIBezierPath *)path {
if (0 != self.borderWidth && nil != self.borderColor) {
[path setLineWidth:2 * self.borderWidth];
[self.borderColor setStroke];
[path stroke];
}
}
- (void)dealloc {
if (self.hadAddObserver) {
[self removeObserver:self forKeyPath:@"image"];
}
}
- (void)validateFrame {
if (self.frame.size.width == 0) {
[self.class swizzleMethod:@selector(layoutSubviews) anotherMethod:@selector(zy_LayoutSubviews)];
}
}
+ (void)swizzleMethod:(SEL)oneSel anotherMethod:(SEL)anotherSel {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Method oneMethod = class_getInstanceMethod(self, oneSel);
Method anotherMethod = class_getInstanceMethod(self, anotherSel);
method_exchangeImplementations(oneMethod, anotherMethod);
});
}
- (void)zy_LayoutSubviews {
[super layoutSubviews];
if (self.isRounding) {
[self zy_cornerRadiusWithImage:self.image cornerRadius:self.frame.size.width/2 rectCornerType:UIRectCornerAllCorners];
} else if (0 != self.radius && 0 != self.roundingCorners && nil != self.image) {
[self zy_cornerRadiusWithImage:self.image cornerRadius:self.radius rectCornerType:self.roundingCorners];
}
}
#pragma mark - KVO for .image
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqualToString:@"image"]) {
UIImage *newImage = change[NSKeyValueChangeNewKey];
if ([newImage isMemberOfClass:[NSNull class]]) {
return;
} else if ([objc_getAssociatedObject(newImage, &kProcessedImage) intValue] == 1) {
return;
}
[self validateFrame];
if (self.isRounding) {
[self zy_cornerRadiusWithImage:newImage cornerRadius:self.frame.size.width/2 rectCornerType:UIRectCornerAllCorners];
} else if (0 != self.radius && 0 != self.roundingCorners && nil != self.image) {
[self zy_cornerRadiusWithImage:newImage cornerRadius:self.radius rectCornerType:self.roundingCorners];
}
}
}
#pragma mark property
- (CGFloat)borderWidth {
return [objc_getAssociatedObject(self, &kBorderWidth) floatValue];
}
- (void)setBorderWidth:(CGFloat)borderWidth {
objc_setAssociatedObject(self, &kBorderWidth, @(borderWidth), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (UIColor *)borderColor {
return objc_getAssociatedObject(self, &kBorderColor);
}
- (void)setBorderColor:(UIColor *)borderColor {
objc_setAssociatedObject(self, &kBorderColor, borderColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (BOOL)hadAddObserver {
return [objc_getAssociatedObject(self, &kHadAddObserver) boolValue];
}
- (void)setHadAddObserver:(BOOL)hadAddObserver {
objc_setAssociatedObject(self, &kHadAddObserver, @(hadAddObserver), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (BOOL)isRounding {
return [objc_getAssociatedObject(self, &kIsRounding) boolValue];
}
- (void)setIsRounding:(BOOL)isRounding {
objc_setAssociatedObject(self, &kIsRounding, @(isRounding), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (UIRectCorner)roundingCorners {
return [objc_getAssociatedObject(self, &kRoundingCorners) unsignedLongValue];
}
- (void)setRoundingCorners:(UIRectCorner)roundingCorners {
objc_setAssociatedObject(self, &kRoundingCorners, @(roundingCorners), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (CGFloat)radius {
return [objc_getAssociatedObject(self, &kRadius) floatValue];
}
- (void)setRadius:(CGFloat)radius {
objc_setAssociatedObject(self, &kRadius, @(radius), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end

View File

@ -0,0 +1,194 @@
//
//
// github:https://github.com/MxABC/LBXScan
//
@import UIKit;
@import Foundation;
@import AVFoundation;
#import "LBXScanTypes.h"
#define LBXScan_Define_Native
/**
@brief ios系统自带扫码功能
*/
@interface LBXScanNative : NSObject
/// 是否需要条码位置信息,默认NO,位置信息在LBXScanResult中返回
@property (nonatomic, assign) BOOL needCodePosion;
///连续扫码默认NO
@property (nonatomic, assign) BOOL continuous;
//default AVCaptureVideoOrientationPortrait
@property (nonatomic, assign) AVCaptureVideoOrientation orientation;
@property (nonatomic, assign) CGRect videoLayerframe;
//相机启动完成
@property (nonatomic, copy) void (^onStarted)(void);
#pragma mark --初始化
/**
@brief
@param preView
@param objType nil(QRAVMetadataObjectTypeQRCode,AVMetadataObjectTypeCode93Code
@param success
@return LBXScanNative的实例
*/
- (instancetype)initWithPreView:(UIView*)preView
ObjectType:(NSArray*)objType
success:(void(^)(NSArray<LBXScanResult*> *array))success;
/**
@brief
@param preView
@param objType nil(QRAVMetadataObjectTypeQRCode,AVMetadataObjectTypeCode93Code
@param blockvideoMaxScale
@param success
@return LBXScanNative的实例
*/
- (instancetype)initWithPreView:(UIView*)preView
ObjectType:(NSArray*)objType
videoMaxScale:(void(^)(CGFloat maxScale))blockvideoMaxScale
success:(void(^)(NSArray<LBXScanResult*> *array))success;
/**
@brief
@param preView
@param objType nil(QRAVMetadataObjectTypeQRCode,AVMetadataObjectTypeCode93Code
@param cropRect CGRectZero
@param success
@return LBXScanNative的实例
*/
- (instancetype)initWithPreView:(UIView*)preView
ObjectType:(NSArray*)objType
cropRect:(CGRect)cropRect
success:(void(^)(NSArray<LBXScanResult*> *array))success;
/**
@brief
@param preView
@param objType nil(QRAVMetadataObjectTypeQRCode,AVMetadataObjectTypeCode93Code
@param cropRect CGRectZero
@param blockvideoMaxScale
@param success
@return LBXScanNative的实例
*/
- (instancetype)initWithPreView:(UIView*)preView
ObjectType:(NSArray*)objType
cropRect:(CGRect)cropRect
videoMaxScale:(void(^)(CGFloat maxScale))blockvideoMaxScale
success:(void(^)(NSArray<LBXScanResult*> *array))success;
#pragma mark --设备控制
/*!
*
*/
- (void)startScan;
/*!
*
*/
- (void)stopScan;
/*!
*
*/
- (BOOL)hasTorch;
/**
*
*
* @param torch ...
*/
- (void)setTorch:(BOOL)torch;
/*!
*
*/
- (void)changeTorch;
/**
*
*
* @param objType type
*/
- (void)changeScanType:(NSArray*)objType;
/*!
*
*
* @param isNeedCaputureImg YES: NO:
*/
- (void)setNeedCaptureImage:(BOOL)isNeedCaputureImg;
#pragma mark --镜头
/**
@brief
@return
*/
- (CGFloat)getVideoMaxScale;
/**
@brief
@param scale
*/
- (void)setVideoScale:(CGFloat)scale;
#pragma mark --识别图片
/**
QR二维码图片,ios8.0
@param image
@param block
*/
+ (void)recognizeImage:(UIImage*)image success:(void(^)(NSArray<LBXScanResult*> *array))block;
#pragma mark --生成条码
/**
QR二维码
@param text
@param size
@return
*/
+ (UIImage*)createQRWithString:(NSString*)text QRSize:(CGSize)size;
/**
QR二维码
@param text
@param size
@param qrColor
@param bkColor
@return
*/
+ (UIImage*)createQRWithString:(NSString*)text QRSize:(CGSize)size QRColor:(UIColor*)qrColor bkColor:(UIColor*)bkColor;
/**
@param text
@param size
@return
*/
+ (UIImage*)createBarCodeWithString:(NSString*)text QRSize:(CGSize)size;
@end

View File

@ -0,0 +1,850 @@
#import "LBXScanNative.h"
@interface LBXScanNative()<AVCaptureMetadataOutputObjectsDelegate>
{
BOOL bNeedScanResult;
}
@property (assign,nonatomic)AVCaptureDevice * device;
@property (strong,nonatomic)AVCaptureDeviceInput * input;
@property (strong,nonatomic)AVCaptureMetadataOutput * output;
@property (strong,nonatomic)AVCaptureSession * session;
@property (strong,nonatomic)AVCaptureVideoPreviewLayer * preview;
@property(nonatomic,strong) AVCaptureStillImageOutput *stillImageOutput;//
@property(nonatomic,assign)BOOL isNeedCaputureImage;
@property (nonatomic, assign) BOOL starting;
@property (nonatomic, strong) NSMutableArray<LBXScanResult*> *arrayResult;
@property (nonatomic, strong) NSArray* arrayBarCodeType;
/**
@brief
*/
@property (nonatomic,weak)UIView *videoPreView;
/*!
*
*/
@property(nonatomic,copy)void (^blockScanResult)(NSArray<LBXScanResult*> *array);
@property (nonatomic, copy) void (^blockvideoMaxScale)(CGFloat maxScale);
@end
@implementation LBXScanNative
- (void)setNeedCaptureImage:(BOOL)isNeedCaputureImg
{
_isNeedCaputureImage = isNeedCaputureImg;
}
- (instancetype)initWithPreView:(UIView*)preView
ObjectType:(NSArray*)objType
videoMaxScale:(void(^)(CGFloat maxScale))blockvideoMaxScale
success:(void(^)(NSArray<LBXScanResult*> *array))success
{
if (self = [super init]) {
[self initParaWithPreView:preView ObjectType:objType cropRect:CGRectZero videoMaxScale:blockvideoMaxScale success:success];
}
return self;
}
- (instancetype)initWithPreView:(UIView*)preView
ObjectType:(NSArray*)objType
success:(void(^)(NSArray<LBXScanResult*> *array))success
{
if (self = [super init]) {
[self initParaWithPreView:preView ObjectType:objType cropRect:CGRectZero videoMaxScale:nil success:success];
}
return self;
}
- (instancetype)initWithPreView:(UIView*)preView
ObjectType:(NSArray*)objType
cropRect:(CGRect)cropRect
videoMaxScale:(void(^)(CGFloat maxScale))blockvideoMaxScale
success:(void(^)(NSArray<LBXScanResult*> *array))success
{
if (self = [super init]) {
[self initParaWithPreView:preView ObjectType:objType cropRect:cropRect videoMaxScale:blockvideoMaxScale success:success];
}
return self;
}
- (instancetype)initWithPreView:(UIView*)preView
ObjectType:(NSArray*)objType
cropRect:(CGRect)cropRect
success:(void(^)(NSArray<LBXScanResult*> *array))success
{
if (self = [super init]) {
[self initParaWithPreView:preView ObjectType:objType cropRect:cropRect videoMaxScale:nil success:success];
}
return self;
}
- (void)initParaWithPreView:(UIView*)videoPreView
ObjectType:(NSArray*)objType
cropRect:(CGRect)cropRect
videoMaxScale:(void(^)(CGFloat maxScale))blockvideoMaxScale
success:(void(^)(NSArray<LBXScanResult*> *array))success
{
self.needCodePosion = NO;
self.continuous = NO;
self.starting = NO;
self.orientation = AVCaptureVideoOrientationPortrait;
self.blockvideoMaxScale = blockvideoMaxScale;
self.arrayBarCodeType = objType;
self.blockScanResult = success;
self.videoPreView = videoPreView;
_device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
if (!_device) {
return;
}
// Input
_input = [AVCaptureDeviceInput deviceInputWithDevice:self.device error:nil];
if ( !_input )
return ;
bNeedScanResult = YES;
// Output
_output = [[AVCaptureMetadataOutput alloc]init];
[_output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
if ( !CGRectEqualToRect(cropRect,CGRectZero) )
{
_output.rectOfInterest = cropRect;
}
/*
// Setup the still image file output
*/
// AVCapturePhotoOutput
_stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys:
AVVideoCodecJPEG, AVVideoCodecKey,
nil];
[_stillImageOutput setOutputSettings:outputSettings];
// Session
_session = [[AVCaptureSession alloc]init];
[_session setSessionPreset:AVCaptureSessionPresetHigh];
// [_session setSessionPreset:AVCaptureSessionPreset1280x720];
if ([_session canAddInput:_input])
{
[_session addInput:_input];
}
if ([_session canAddOutput:_output])
{
[_session addOutput:_output];
}
if ([_session canAddOutput:_stillImageOutput])
{
[_session addOutput:_stillImageOutput];
}
// AVMetadataObjectTypeQRCode
// _output.metadataObjectTypes =@[AVMetadataObjectTypeQRCode];
if (!objType) {
objType = [self defaultMetaDataObjectTypes];
}
_output.metadataObjectTypes = objType;
// Preview
_preview =[AVCaptureVideoPreviewLayer layerWithSession:_session];
_preview.videoGravity = AVLayerVideoGravityResizeAspectFill;
// _preview
//_preview.frame =CGRectMake(20,110,280,280);
CGRect frame = videoPreView.frame;
frame.origin = CGPointZero;
_preview.frame = frame;
[videoPreView.layer insertSublayer:self.preview atIndex:0];
if (_blockvideoMaxScale) {
AVCaptureConnection *videoConnection = [self connectionWithMediaType:AVMediaTypeVideo fromConnections:[[self stillImageOutput] connections]];
CGFloat maxScale = videoConnection.videoMaxScaleAndCropFactor;
CGFloat scale = videoConnection.videoScaleAndCropFactor;
NSLog(@"max:%F cur:%f",maxScale,scale);
_blockvideoMaxScale(maxScale);
}
//,
if (_device.isFocusPointOfInterestSupported &&[_device isFocusModeSupported:AVCaptureFocusModeAutoFocus])
{
[_input.device lockForConfiguration:nil];
[_input.device setFocusMode:AVCaptureFocusModeContinuousAutoFocus];
[_input.device unlockForConfiguration];
}
}
- (CGFloat)getVideoMaxScale
{
[_input.device lockForConfiguration:nil];
AVCaptureConnection *videoConnection = [self connectionWithMediaType:AVMediaTypeVideo fromConnections:[[self stillImageOutput] connections]];
CGFloat maxScale = videoConnection.videoMaxScaleAndCropFactor;
[_input.device unlockForConfiguration];
return maxScale;
}
- (void)setVideoScale:(CGFloat)scale
{
[_input.device lockForConfiguration:nil];
AVCaptureConnection *videoConnection = [self connectionWithMediaType:AVMediaTypeVideo fromConnections:[[self stillImageOutput] connections]];
if (scale < 1 || scale > videoConnection.videoMaxScaleAndCropFactor ) {
return;
}
CGFloat zoom = scale / videoConnection.videoScaleAndCropFactor;
// NSLog(@"max :%f",videoConnection.videoMaxScaleAndCropFactor);
videoConnection.videoScaleAndCropFactor = scale;
[_input.device unlockForConfiguration];
CGAffineTransform transform = _videoPreView.transform;
_videoPreView.transform = CGAffineTransformScale(transform, zoom, zoom);
// CGFloat y = 0;
// y = y + zoom > 1 ? zoom : -zoom;
// //
// _videoPreView.transform = CGAffineTransformTranslate(_videoPreView.transform, 0, y);
}
- (void)setScanRect:(CGRect)scanRect
{
if (_output) {
_output.rectOfInterest = [self.preview metadataOutputRectOfInterestForRect:scanRect];
}
}
- (void)changeScanType:(NSArray*)objType
{
_output.metadataObjectTypes = objType;
}
- (void)setOrientation:(AVCaptureVideoOrientation)orientation
{
_orientation = orientation;
if ( _input )
{
self.preview.connection.videoOrientation = self.orientation;
}
}
- (void)setVideoLayerframe:(CGRect)videoLayerframe
{
self.preview.frame = videoLayerframe;
}
- (void)startScan
{
if ( !_starting && _input && !_session.isRunning )
{
_starting = YES;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
self.preview.connection.videoOrientation = self.orientation;
[self.session startRunning];
self->bNeedScanResult = YES;
self.starting = NO;
dispatch_async(dispatch_get_main_queue(), ^{
[self.videoPreView.layer insertSublayer:self.preview atIndex:0];
if (self.onStarted) {
self.onStarted();
}
});
});
}
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ( object == _input.device ) {
NSLog(@"flash change");
}
}
- (void)stopScan
{
bNeedScanResult = NO;
if ( _input && _session.isRunning )
{
bNeedScanResult = NO;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self.session stopRunning];
self.starting = NO;
});
}
}
- (BOOL)hasTorch
{
return [_input.device hasTorch];
}
- (void)setTorch:(BOOL)torch {
if ([self.input.device hasTorch]) {
NSError *error = nil;
if([self.input.device lockForConfiguration:&error])
self.input.device.torchMode = torch ? AVCaptureTorchModeOn : AVCaptureTorchModeOff;
[self.input.device unlockForConfiguration];
}
}
- (void)changeTorch
{
if ([self.input.device hasTorch]) {
AVCaptureTorchMode torch = self.input.device.torchMode;
switch (_input.device.torchMode) {
case AVCaptureTorchModeAuto:
break;
case AVCaptureTorchModeOff:
torch = AVCaptureTorchModeOn;
break;
case AVCaptureTorchModeOn:
torch = AVCaptureTorchModeOff;
break;
default:
break;
}
[_input.device lockForConfiguration:nil];
_input.device.torchMode = torch;
[_input.device unlockForConfiguration];
}
}
-(UIImage *)getImageFromLayer:(CALayer *)layer size:(CGSize)size
{
UIGraphicsBeginImageContextWithOptions(size, YES, [[UIScreen mainScreen]scale]);
[layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
- (AVCaptureConnection *)connectionWithMediaType:(NSString *)mediaType fromConnections:(NSArray *)connections
{
for ( AVCaptureConnection *connection in connections ) {
for ( AVCaptureInputPort *port in [connection inputPorts] ) {
if ( [[port mediaType] isEqual:mediaType] ) {
return connection;
}
}
}
return nil;
}
- (void)captureImage
{
AVCaptureConnection *stillImageConnection = [self connectionWithMediaType:AVMediaTypeVideo fromConnections:[[self stillImageOutput] connections]];
[[self stillImageOutput] captureStillImageAsynchronouslyFromConnection:stillImageConnection
completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error)
{
if (!self.continuous) {
[self stopScan];
}
if (imageDataSampleBuffer)
{
NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
UIImage *img = [UIImage imageWithData:imageData];
for (LBXScanResult* result in self.arrayResult) {
result.imgScanned = img;
}
}
if (self.blockScanResult)
{
self.blockScanResult(self.arrayResult);
}
}];
}
#pragma mark AVCaptureMetadataOutputObjectsDelegate
- (void)captureOutput2:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
{
//
for(AVMetadataObject *current in metadataObjects)
{
if ([current isKindOfClass:[AVMetadataMachineReadableCodeObject class]] )
{
NSString *scannedResult = [(AVMetadataMachineReadableCodeObject *) current stringValue];
NSLog(@"type:%@",current.type);
NSLog(@"result:%@",scannedResult);
//
}
}
}
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
{
if (!bNeedScanResult) {
return;
}
bNeedScanResult = NO;
if (!_arrayResult) {
self.arrayResult = [NSMutableArray arrayWithCapacity:1];
}
else
{
[_arrayResult removeAllObjects];
}
metadataObjects = [self transformedCodesFromCodes:metadataObjects];
//
for(AVMetadataObject *current in metadataObjects)
{
if ([current isKindOfClass:[AVMetadataMachineReadableCodeObject class]] )
{
bNeedScanResult = NO;
NSLog(@"type:%@",current.type);
NSString *scannedResult = [(AVMetadataMachineReadableCodeObject *) current stringValue];
NSArray<NSDictionary *> *corners = ((AVMetadataMachineReadableCodeObject *) current).corners;
CGRect bounds = ((AVMetadataMachineReadableCodeObject *) current).bounds;
NSLog(@"corners:%@ bounds:%@",corners,NSStringFromCGRect( bounds ));
if (scannedResult && ![scannedResult isEqualToString:@""])
{
LBXScanResult *result = [LBXScanResult new];
result.strScanned = scannedResult;
result.strBarCodeType = current.type;
result.corners = corners;
result.bounds = bounds;
[_arrayResult addObject:result];
}
//
}
}
if (_arrayResult.count < 1)
{
bNeedScanResult = YES;
return;
}
if (!_continuous && !_needCodePosion && _isNeedCaputureImage)
{
[self captureImage];
}
else
{
if (!_continuous) {
[self stopScan];
}
if (_blockScanResult) {
_blockScanResult(_arrayResult);
}
}
if (_continuous) {
bNeedScanResult = YES;
}
}
- (NSArray *)transformedCodesFromCodes:(NSArray *)codes {
NSMutableArray *transformedCodes = [NSMutableArray array];
[codes enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
AVMetadataObject *transformedCode = [self.preview transformedMetadataObjectForMetadataObject:obj];
[transformedCodes addObject:transformedCode];
}];
return [transformedCodes copy];
}
- (CGPoint)pointForCorner:(NSDictionary *)corner {
CGPoint point;
CGPointMakeWithDictionaryRepresentation((CFDictionaryRef)corner, &point);
return point;
}
- (void)handCorners:(NSArray<NSDictionary *> *)corners bounds:(CGRect)bounds
{
CGFloat totalX = 0;
CGFloat totalY = 0;
for (NSDictionary *dic in corners) {
CGPoint pt = [self pointForCorner:dic];
NSLog(@"pt:%@",NSStringFromCGPoint(pt));
totalX += pt.x;
totalY += pt.y;
}
CGFloat averX = totalX / corners.count;
CGFloat averY = totalY / corners.count;
CGFloat minSize = MIN(bounds.size.width , bounds.size.height);
NSLog(@"averx:%f,avery:%f minsize:%f",averX,averY,minSize);
dispatch_async(dispatch_get_main_queue(), ^{
[self signCodeWithCenterX:averX centerY:averY];
});
}
- (void)signCodeWithCenterX:(CGFloat)centerX centerY:(CGFloat)centerY
{
UIView *signView = [[UIView alloc]initWithFrame:CGRectMake(centerX-10, centerY-10, 20, 20)];
[self.videoPreView addSubview:signView];
signView.backgroundColor = [UIColor redColor];
}
///
/// @param averX averX descriptio
/// @param averY averY description
/// @param bounds bounds description
- (void)videoNearCode:(CGFloat)averX averY:(CGFloat)averY bounds:(CGRect)bounds
{
CGFloat minSize = MIN(bounds.size.width , bounds.size.height);
// CGFloat y = 0;
// y = y + zoom > 1 ? zoom : -zoom;
// //
// _videoPreView.transform = CGAffineTransformTranslate(_videoPreView.transform, 0, y);
CGFloat width = _videoPreView.bounds.size.width;
CGFloat height = _videoPreView.bounds.size.height;
CGFloat centerX = width / 2;
CGFloat centerY = height / 2;
CGFloat diffX = centerX - averX;
CGFloat diffY = centerY - averY;
//
CGFloat scale = 100 / minSize * 1.1;
NSLog(@"diffX:%f,diffY:%f,scale:%f",diffX,diffY,scale);
diffX = diffX / MAX(1, scale * 0.8);
diffY = diffY / MAX(1, scale * 0.8);
if (scale > 1) {
[_input.device lockForConfiguration:nil];
AVCaptureConnection *videoConnection = [self connectionWithMediaType:AVMediaTypeVideo fromConnections:[[self stillImageOutput] connections]];
if (scale < 1 || scale > videoConnection.videoMaxScaleAndCropFactor ) {
return;
}
CGFloat zoom = scale / videoConnection.videoScaleAndCropFactor;
videoConnection.videoScaleAndCropFactor = scale;
[_input.device unlockForConfiguration];
CGAffineTransform transform = _videoPreView.transform;
[UIView animateWithDuration:0.3 animations:^{
self.videoPreView.transform = CGAffineTransformScale(transform, zoom, zoom);
}];
[UIView animateWithDuration:0.3 animations:^{
self.videoPreView.transform = CGAffineTransformTranslate(self.videoPreView.transform,diffX , diffY);
}];
}
}
/**
@brief
@return
*/
- (NSArray *)defaultMetaDataObjectTypes
{
NSMutableArray *types = [@[AVMetadataObjectTypeQRCode,
AVMetadataObjectTypeUPCECode,
AVMetadataObjectTypeCode39Code,
AVMetadataObjectTypeCode39Mod43Code,
AVMetadataObjectTypeEAN13Code,
AVMetadataObjectTypeEAN8Code,
AVMetadataObjectTypeCode93Code,
AVMetadataObjectTypeCode128Code,
AVMetadataObjectTypePDF417Code,
AVMetadataObjectTypeAztecCode] mutableCopy];
if (@available(iOS 8.0, *)) {
[types addObjectsFromArray:@[
AVMetadataObjectTypeInterleaved2of5Code,
AVMetadataObjectTypeITF14Code,
AVMetadataObjectTypeDataMatrixCode
]];
}
return types;
}
#pragma mark --
+ (void)recognizeImage:(UIImage*)image success:(void(^)(NSArray<LBXScanResult*> *array))block;
{
if (!image) {
block(nil);
return;
}
if (@available(iOS 8.0, *)) {
CIImage * cimg = [CIImage imageWithCGImage:image.CGImage];
if (!cimg) {
block(nil);
return;
}
NSArray *features = nil;
@try {
CIDetector*detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:nil options:@{ CIDetectorAccuracy : CIDetectorAccuracyHigh }];
features = [detector featuresInImage:cimg];
} @catch (NSException *exception) {
block(nil);
return;
} @finally {
}
NSMutableArray<LBXScanResult*> *mutableArray = [[NSMutableArray alloc]initWithCapacity:1];
for (int index = 0; index < [features count]; index ++)
{
CIQRCodeFeature *feature = [features objectAtIndex:index];
NSString *scannedResult = feature.messageString;
LBXScanResult *item = [[LBXScanResult alloc]init];
item.strScanned = scannedResult;
item.strBarCodeType = CIDetectorTypeQRCode;
item.imgScanned = image;
[mutableArray addObject:item];
}
if (block) {
block(mutableArray);
}
}else{
if (block) {
LBXScanResult *result = [[LBXScanResult alloc]init];
result.strScanned = @"只支持ios8.0之后系统";
block(@[result]);
}
}
}
#pragma mark --
// https://github.com/yourtion/Demo_CustomQRCode
#pragma mark - InterpolatedUIImage
+ (UIImage *)createNonInterpolatedUIImageFormCIImage:(CIImage *)image withSize:(CGFloat) size {
CGRect extent = CGRectIntegral(image.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);
CGColorSpaceRelease(cs);
CIContext *context = [CIContext contextWithOptions:nil];
CGImageRef bitmapImage = [context createCGImage:image fromRect:extent];
CGContextSetInterpolationQuality(bitmapRef, kCGInterpolationNone);
CGContextScaleCTM(bitmapRef, scale, scale);
CGContextDrawImage(bitmapRef, extent, bitmapImage);
// bitmap
CGImageRef scaledImage = CGBitmapContextCreateImage(bitmapRef);
CGContextRelease(bitmapRef);
CGImageRelease(bitmapImage);
UIImage *aImage = [UIImage imageWithCGImage:scaledImage];
CGImageRelease(scaledImage);
return aImage;
}
#pragma mark - QRCodeGenerator
+ (CIImage *)createQRForString:(NSString *)qrString {
NSData *stringData = [qrString dataUsingEncoding:NSUTF8StringEncoding];
// filter
CIFilter *qrFilter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
//
[qrFilter setValue:stringData forKey:@"inputMessage"];
[qrFilter setValue:@"H" forKey:@"inputCorrectionLevel"];
// CIImage
return qrFilter.outputImage;
}
#pragma mark -
+ (UIImage*)createQRWithString:(NSString*)text QRSize:(CGSize)size
{
NSData *stringData = [text dataUsingEncoding: NSUTF8StringEncoding];
//
CIFilter *qrFilter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
[qrFilter setValue:stringData forKey:@"inputMessage"];
[qrFilter setValue:@"H" forKey:@"inputCorrectionLevel"];
CIImage *qrImage = qrFilter.outputImage;
//
CGImageRef cgImage = [[CIContext contextWithOptions:nil] createCGImage:qrImage fromRect:qrImage.extent];
UIGraphicsBeginImageContext(size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetInterpolationQuality(context, kCGInterpolationNone);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextDrawImage(context, CGContextGetClipBoundingBox(context), cgImage);
UIImage *codeImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
CGImageRelease(cgImage);
return codeImage;
}
+ (UIImage*)createQRWithString:(NSString*)text QRSize:(CGSize)size QRColor:(UIColor*)qrColor bkColor:(UIColor*)bkColor
{
NSData *stringData = [text dataUsingEncoding: NSUTF8StringEncoding];
//
CIFilter *qrFilter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
[qrFilter setValue:stringData forKey:@"inputMessage"];
[qrFilter setValue:@"H" forKey:@"inputCorrectionLevel"];
//
CIFilter *colorFilter = [CIFilter filterWithName:@"CIFalseColor"
keysAndValues:
@"inputImage",qrFilter.outputImage,
@"inputColor0",[CIColor colorWithCGColor:qrColor.CGColor],
@"inputColor1",[CIColor colorWithCGColor:bkColor.CGColor],
nil];
CIImage *qrImage = colorFilter.outputImage;
//
CGImageRef cgImage = [[CIContext contextWithOptions:nil] createCGImage:qrImage fromRect:qrImage.extent];
UIGraphicsBeginImageContext(size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetInterpolationQuality(context, kCGInterpolationNone);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextDrawImage(context, CGContextGetClipBoundingBox(context), cgImage);
UIImage *codeImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
CGImageRelease(cgImage);
return codeImage;
}
+ (UIImage*)createBarCodeWithString:(NSString*)text QRSize:(CGSize)size
{
NSData *data = [text dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:false];
CIFilter *filter = [CIFilter filterWithName:@"CICode128BarcodeGenerator"];
[filter setValue:data forKey:@"inputMessage"];
CIImage *barcodeImage = [filter outputImage];
//
CGFloat scaleX = size.width / barcodeImage.extent.size.width; // extent frame
CGFloat scaleY = size.height / barcodeImage.extent.size.height;
CIImage *transformedImage = [barcodeImage imageByApplyingTransform:CGAffineTransformScale(CGAffineTransformIdentity, scaleX, scaleY)];
return [UIImage imageWithCIImage:transformedImage];
}
@end

View File

@ -0,0 +1,35 @@
//
//
//
// github:https://github.com/MxABC/LBXScan
//
@import UIKit;
@import Foundation;
@interface LBXScanResult : NSObject
- (instancetype)initWithScanString:(NSString*)str imgScan:(UIImage*)img barCodeType:(NSString*)type;
/**
@brief
*/
@property (nonatomic, copy) NSString* strScanned;
/**
@brief
*/
@property (nonatomic, strong) UIImage* imgScanned;
/**
@brief ,AVMetadataObjectType AVMetadataObjectTypeQRCodeAVMetadataObjectTypeEAN13Code等
*/
@property (nonatomic, copy) NSString* strBarCodeType;
//条码4个角
@property (nonatomic, copy) NSArray<NSDictionary *> *corners;
//没有corners精确
@property (nonatomic, assign) CGRect bounds;
@end

View File

@ -0,0 +1,22 @@
#import "LBXScanTypes.h"
@implementation LBXScanResult
- (instancetype)initWithScanString:(NSString*)str imgScan:(UIImage*)img barCodeType:(NSString*)type
{
if (self = [super init]) {
self.strScanned = str;
self.imgScanned = img;
self.strBarCodeType = type;
self.bounds = CGRectZero;
}
return self;
}
@end

View File

@ -0,0 +1,20 @@
//
// QrCodeViewController.h
// Unity-iPhone
//
// Created by zhl on 2022/11/24.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface QrCodeViewController : UIViewController
@property (nonatomic, strong) UIImage* imgScan;
@property (nonatomic, copy) NSString* content;
@property (nonatomic, copy) NSString* tipTitle;
@property (nonatomic, assign) BOOL autosave;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,82 @@
//
// QrCodeViewController.m
// Unity-iPhone
//
// Created by zhl on 2022/11/24.
//
#import "QrCodeViewController.h"
#include "LBXScanNative.h"
@interface QrCodeViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *scanImg;
@property (weak, nonatomic) IBOutlet UIView *container;
@property (weak, nonatomic) IBOutlet UILabel *titleLabel;
@property (weak, nonatomic) IBOutlet UIButton *closeBtn;
@property (weak, nonatomic) IBOutlet UITextView *textView;
@end
@implementation QrCodeViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[_closeBtn addTarget:self action:@selector(dismissSelf:) forControlEvents:UIControlEventTouchUpInside];
self.container.backgroundColor = [UIColor whiteColor];
self.container.layer.shadowOffset = CGSizeMake(0, 2);
self.container.layer.shadowRadius = 2;
self.container.layer.shadowColor = [UIColor blackColor].CGColor;
self.container.layer.shadowOpacity = 0.5;
}
/*
#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.
}
*/
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if (!_imgScan) {
_scanImg.backgroundColor = [UIColor grayColor];
if (_content) {
CGSize _size = _scanImg.frame.size;
_imgScan = [LBXScanNative createQRWithString:_content QRSize:_size];
}
}
_titleLabel.text = _tipTitle;
_scanImg.image = _imgScan;
if (_autosave) {
[self saveToPhotoLibrary];
}
}
// save qr image to Camera Roll album
-(void) saveToPhotoLibrary {
UIGraphicsBeginImageContextWithOptions(self.container.bounds.size, NO, 0);
CGContextRef ctx = UIGraphicsGetCurrentContext();
[self.container.layer renderInContext:ctx];
UIImage * newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageWriteToSavedPhotosAlbum(newImage, self, @selector(image:didFinishSavingWithError:contextInfo:), NULL);
}
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
{
if (error) {
NSLog(@"保存失败");
} else {
NSLog(@"保存成功");
}
}
-(void)dismissSelf:(UIButton *)button{
[self dismissViewControllerAnimated:YES completion:nil];
}
@end

View File

@ -0,0 +1,107 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina6_1" orientation="landscape" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="QrCodeViewController">
<connections>
<outlet property="closeBtn" destination="ARv-35-WSy" id="822-Id-lUS"/>
<outlet property="container" destination="fpG-y0-v4j" id="jpQ-po-eFA"/>
<outlet property="scanImg" destination="RbQ-nc-PEN" id="RaM-Wf-FXx"/>
<outlet property="textView" destination="O4k-Xx-lNi" id="g5n-oI-kNK"/>
<outlet property="titleLabel" destination="FUd-A4-OOf" id="dt5-bR-8rI"/>
<outlet property="view" destination="iN0-l3-epB" id="SAp-0A-eXx"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="iN0-l3-epB">
<rect key="frame" x="0.0" y="0.0" width="896" height="414"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" textAlignment="natural" translatesAutoresizingMaskIntoConstraints="NO" id="O4k-Xx-lNi">
<rect key="frame" x="568" y="103" width="240" height="248"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstAttribute="width" constant="240" id="AgP-iJ-PiA"/>
<constraint firstAttribute="height" constant="248" id="X7c-Eh-aot"/>
</constraints>
<string key="text">Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda.</string>
<color key="textColor" systemColor="labelColor"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
</textView>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ARv-35-WSy">
<rect key="frame" x="84" y="40" width="80" height="31"/>
<constraints>
<constraint firstAttribute="width" constant="80" id="0fF-Qx-qH4"/>
<constraint firstAttribute="height" constant="31" id="50h-Rz-9MN"/>
</constraints>
<inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
<state key="normal" title="Close"/>
<buttonConfiguration key="configuration" style="tinted" title="Close"/>
</button>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="fpG-y0-v4j">
<rect key="frame" x="318" y="62" width="260" height="290"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="FUd-A4-OOf">
<rect key="frame" x="111.5" y="15.5" width="37.5" height="19"/>
<fontDescription key="fontDescription" type="system" pointSize="15"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
<color key="shadowColor" white="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</label>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="RbQ-nc-PEN">
<rect key="frame" x="10" y="41" width="240" height="248"/>
<constraints>
<constraint firstAttribute="width" constant="240" id="Cbb-mq-5af"/>
<constraint firstAttribute="height" constant="248" id="Z3x-IW-dpK"/>
</constraints>
</imageView>
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstItem="FUd-A4-OOf" firstAttribute="centerY" secondItem="fpG-y0-v4j" secondAttribute="centerY" constant="-120" id="0Oc-BH-TJm"/>
<constraint firstItem="RbQ-nc-PEN" firstAttribute="centerY" secondItem="fpG-y0-v4j" secondAttribute="centerY" constant="20" id="8Gc-BQ-00x"/>
<constraint firstItem="RbQ-nc-PEN" firstAttribute="centerX" secondItem="fpG-y0-v4j" secondAttribute="centerX" id="kVG-XR-Utx"/>
<constraint firstAttribute="width" constant="260" id="lFZ-QX-JYR"/>
<constraint firstItem="FUd-A4-OOf" firstAttribute="centerX" secondItem="fpG-y0-v4j" secondAttribute="centerX" id="r3w-zS-uVw"/>
<constraint firstAttribute="height" constant="290" id="x41-u7-bAe"/>
</constraints>
</view>
</subviews>
<viewLayoutGuide key="safeArea" id="vUN-kp-3ea"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstItem="fpG-y0-v4j" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="centerY" id="56v-Gg-QJh"/>
<constraint firstItem="ARv-35-WSy" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="centerY" constant="-110" id="94T-iZ-mPQ"/>
<constraint firstItem="ARv-35-WSy" firstAttribute="top" secondItem="vUN-kp-3ea" secondAttribute="top" constant="40" id="96a-om-YCg"/>
<constraint firstItem="ARv-35-WSy" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" constant="-210" id="M0S-Ry-qx7"/>
<constraint firstItem="fpG-y0-v4j" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" id="Pgv-CL-voZ"/>
<constraint firstItem="O4k-Xx-lNi" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="centerY" constant="20" id="T7p-OA-zZd"/>
<constraint firstItem="ARv-35-WSy" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" constant="40" id="a7T-fb-xLU"/>
<constraint firstItem="O4k-Xx-lNi" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" constant="240" id="zwm-x2-DV7"/>
</constraints>
<variation key="default">
<mask key="constraints">
<exclude reference="94T-iZ-mPQ"/>
<exclude reference="M0S-Ry-qx7"/>
</mask>
</variation>
<point key="canvasLocation" x="139" y="115"/>
</view>
</objects>
<resources>
<systemColor name="labelColor">
<color white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
</resources>
</document>

View File

@ -14,12 +14,20 @@
#include "JcWallet.h"
#import <GoogleSignIn/GoogleSignIn.h>
#include "KeyChain/DataManager.h"
#include "permission/LBXPermission.h"
#include "permission/LBXPermissionSetting.h"
#include "LBXScanNative.h"
#include "LBXScanTypes.h"
#include "QrCodeViewController.h"
@import GoogleSignIn;
static NSString * const kClientID =
@"53206975661-0d6q9pqljn84n9l63gm0to1ulap9cbk4.apps.googleusercontent.com";
@interface UIViewController (Wallet)<UIImagePickerControllerDelegate, UINavigationControllerDelegate>
@end
@implementation UIViewController (Wallet)
+(void)toWallet:(NSString *)url{
@ -29,80 +37,95 @@ static NSString * const kClientID =
-(void)showQRCode:(NSString *) content title:(NSString *) title oid:(NSString *) oid {
NSLog(@"showQRCode content: %@, title: %@, oid: %@", content, title, oid);
dispatch_async(dispatch_get_main_queue(), ^{
QrCodeViewController *vc = [QrCodeViewController new];
vc.content = content;
vc.tipTitle = title;
vc.autosave = TRUE;
[self presentViewController:vc animated:YES completion:nil];
});
}
-(void)loadRestoreKey:(NSString *)funid oid:(NSString *) oid{
NSLog(@"loadRestoreKey::funid: %@, oid:%@", funid, oid);
}
// save key to key chain
-(void)saveKey:(NSString *) account key:(NSString *) key {
// NSLog(@"saveKey::account:%@, key: %@", account, key);
[[DataManager sharedInstanceWith: SynLock] saveKey: account key: key];
}
// load key from key chain
-(NSString *)loadKey:(NSString *) account {
NSLog(@"loadKey::account:%@", account);
return [[DataManager sharedInstanceWith: SynLock] loadKey: account];
}
-(void)scanQRCode:(NSString *)funid title:(NSString *) title{
NSLog(@"scanQRCode:: funId: %@ title: %@", funid, title);
std::string sfunid = std::string([funid UTF8String], [funid lengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
if ([QRCodeReader supportsMetadataObjectTypes:@[AVMetadataObjectTypeQRCode]]) {
static QRCodeReaderViewController *vc = nil;
static dispatch_once_t onceToken;
dispatch_async(dispatch_get_main_queue(), ^{
// if we are active again, we don't need to do this anymore
if (vc == nil) {
QRCodeReader *reader = [QRCodeReader readerWithMetadataObjectTypes:@[AVMetadataObjectTypeQRCode]];
vc = [QRCodeReaderViewController readerWithCancelButtonTitle:@"Cancel" codeReader:reader startScanningAtLoad:YES showSwitchCameraButton:YES showTorchButton:YES];
vc.modalPresentationStyle = UIModalPresentationFormSheet;
}
[vc setCompletionWithBlock:^(NSString *resultAsString) {
NSLog(@"Completion with result: %@", resultAsString);
[self dismissViewControllerAnimated:YES completion:^{
NSString *result;
if (resultAsString.length > 0) {
result = [NSString stringWithFormat:@"{errcode: 0, data: '%@'}", resultAsString];
} else {
result = [NSString stringWithFormat:@"{errcode: 1, errmsg: 'cancel'}"];
}
std::string sresult = std::string([result UTF8String], [result lengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
WalletEvent::Emit(sfunid.c_str(), sresult.c_str());
}];
}];
[self presentViewController:vc animated:YES completion:NULL];
});
}
else {
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Error"
message:@"The camera is need to scan QR codes"
preferredStyle:UIAlertControllerStyleAlert];
//We add buttons to the alert controller by creating UIAlertActions:
UIAlertAction *actionOk = [UIAlertAction actionWithTitle:@"Cancel"
style:UIAlertActionStyleCancel
handler: ^(UIAlertAction *action){
NSLog(@"alert cancel pressed");
}]; //You can use a block here to handle a press on this button
//
UIAlertAction *setting = [UIAlertAction actionWithTitle:@"Setting"
style:UIAlertActionStyleDefault
handler: ^(UIAlertAction *action){
NSLog(@"setting pressed");
NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
if ([[UIApplication sharedApplication] canOpenURL:url]){
[[UIApplication sharedApplication] openURL:url];
}
}];
[alertController addAction:actionOk];
[alertController addAction:setting];
[self presentViewController:alertController animated:YES completion:nil];
});
std::string sresult = "{errcode: 1, errmsg: 'no camera permission'}";
WalletEvent::Emit(sfunid.c_str(), sresult.c_str());
}
NSLog(@"scanQRCode:: funId: %@ title: %@", funid, title);
dispatch_async(dispatch_get_main_queue(), ^{
[self openLocalPhotoAlbum];
});
// std::string sfunid = std::string([funid UTF8String], [funid lengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
// if ([QRCodeReader supportsMetadataObjectTypes:@[AVMetadataObjectTypeQRCode]]) {
// static QRCodeReaderViewController *vc = nil;
// static dispatch_once_t onceToken;
//
// dispatch_async(dispatch_get_main_queue(), ^{
// // if we are active again, we don't need to do this anymore
// if (vc == nil) {
// QRCodeReader *reader = [QRCodeReader readerWithMetadataObjectTypes:@[AVMetadataObjectTypeQRCode]];
// vc = [QRCodeReaderViewController readerWithCancelButtonTitle:@"Cancel" codeReader:reader startScanningAtLoad:YES showSwitchCameraButton:YES showTorchButton:YES];
// vc.modalPresentationStyle = UIModalPresentationFormSheet;
// }
//
// [vc setCompletionWithBlock:^(NSString *resultAsString) {
// NSLog(@"Completion with result: %@", resultAsString);
// [self dismissViewControllerAnimated:YES completion:^{
//
// NSString *result;
// if (resultAsString.length > 0) {
// result = [NSString stringWithFormat:@"{errcode: 0, data: '%@'}", resultAsString];
// } else {
// result = [NSString stringWithFormat:@"{errcode: 1, errmsg: 'cancel'}"];
// }
// std::string sresult = std::string([result UTF8String], [result lengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
// WalletEvent::Emit(sfunid.c_str(), sresult.c_str());
// }];
// }];
// [self presentViewController:vc animated:YES completion:NULL];
// });
// }
// else {
// dispatch_async(dispatch_get_main_queue(), ^{
// UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Error"
// message:@"The camera is need to scan QR codes"
// preferredStyle:UIAlertControllerStyleAlert];
// //We add buttons to the alert controller by creating UIAlertActions:
// UIAlertAction *actionOk = [UIAlertAction actionWithTitle:@"Cancel"
// style:UIAlertActionStyleCancel
// handler: ^(UIAlertAction *action){
// NSLog(@"alert cancel pressed");
// }]; //You can use a block here to handle a press on this button
// //
// UIAlertAction *setting = [UIAlertAction actionWithTitle:@"Setting"
// style:UIAlertActionStyleDefault
// handler: ^(UIAlertAction *action){
// NSLog(@"setting pressed");
// NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
// if ([[UIApplication sharedApplication] canOpenURL:url]){
// [[UIApplication sharedApplication] openURL:url];
// }
// }];
// [alertController addAction:actionOk];
// [alertController addAction:setting];
// [self presentViewController:alertController animated:YES completion:nil];
// });
//
// std::string sresult = "{errcode: 1, errmsg: 'no camera permission'}";
// WalletEvent::Emit(sfunid.c_str(), sresult.c_str());
// }
}
-(void)signToGoogle:(NSString *) funid {
@ -197,5 +220,81 @@ static NSString * const kClientID =
// }];
}
#pragma mark- - PhotoAlbum
- (void)openLocalPhotoAlbum
{
__weak __typeof(self) weakSelf = self;
[LBXPermission authorizeWithType:LBXPermissionType_Photos completion:^(BOOL granted, BOOL firstTime) {
if (granted) {
[weakSelf openLocalPhoto];
}
else if (!firstTime )
{
[LBXPermissionSetting showAlertToDislayPrivacySettingWithTitle:@"提示" msg:@"没有相册权限,是否前往设置" cancel:@"取消" setting:@"设置"];
}
}];
}
/*!
* open local Photo Library
*/
- (void)openLocalPhoto
{
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
picker.delegate = self;
// crash on some mobile
picker.allowsEditing = NO;
[self presentViewController:picker animated:YES completion:nil];
}
#pragma mark- - UIImagePickerControllerDelegate
-(void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
[picker dismissViewControllerAnimated:YES completion:^{
[self handPhotoDidFinishPickingMediaWithInfo:info];
}];
}
- (void)handPhotoDidFinishPickingMediaWithInfo:(NSDictionary *)info
{
__block UIImage* image = [info objectForKey:UIImagePickerControllerEditedImage];
if (!image){
image = [info objectForKey:UIImagePickerControllerOriginalImage];
}
if (@available(iOS 8.0, *)) {
__weak __typeof(self) weakSelf = self;
[LBXScanNative recognizeImage:image success:^(NSArray<LBXScanResult *> *array) {
[weakSelf scanResultWithArray:array];
}];
}else{
NSLog(@"native低于ios8.0不支持识别图片");
}
}
- (void)scanResultWithArray:(NSArray<LBXScanResult*>*)array
{
if (!array || array.count < 1)
{
NSLog(@"error scan photo");
return;
}
for (LBXScanResult *result in array) {
NSLog(@"scanResult:%@",result.strScanned);
}
if (!array[0].strScanned || [array[0].strScanned isEqualToString:@""] ) {
NSLog(@"识别失败了");
return;
}
LBXScanResult *scanResult = array[0];
}
@end

View File

@ -0,0 +1,71 @@
//
// LBXPermission.h
// LBXKits
// https://github.com/MxABC/LBXPermission
//
#import <Foundation/Foundation.h>
#import "LBXPermissionSetting.h"
typedef NS_ENUM(NSInteger,LBXPermissionType)
{
LBXPermissionType_Location,
LBXPermissionType_Camera,
LBXPermissionType_Photos,
LBXPermissionType_Contacts,
LBXPermissionType_Reminders,
LBXPermissionType_Calendar,
LBXPermissionType_Microphone,
LBXPermissionType_Health,
LBXPermissionType_DataNetwork,
LBXPermissionType_MediaLibrary
};
@interface LBXPermission : NSObject
/**
only effective for location servince,other type reture YES
@param type permission type,when type is not location,return YES
@return YES if system location privacy service enabled NO othersize
*/
+ (BOOL)isServicesEnabledWithType:(LBXPermissionType)type;
/**
whether device support the type
@param type permission type
@return YES if device support
*/
+ (BOOL)isDeviceSupportedWithType:(LBXPermissionType)type;
/**
whether permission has been obtained, only return status, not request permission
for example, u can use this method in app setting, show permission status
in most cases, suggest call "authorizeWithType:completion" method
@param type permission type
@return YES if Permission has been obtained,NO othersize
*/
+ (BOOL)authorizedWithType:(LBXPermissionType)type;
/**
request permission and return status in main thread by block.
execute block immediately when permission has been requested,else request permission and waiting for user to choose "Don't allow" or "Allow"
@param type permission type
@param completion May be called immediately if permission has been requested
granted: YES if permission has been obtained, firstTime: YES if first time to request permission
*/
+ (void)authorizeWithType:(LBXPermissionType)type completion:(void(^)(BOOL granted,BOOL firstTime))completion;
@end

View File

@ -0,0 +1,133 @@
//
// LBXPermission.m
// LBXKits
#import "LBXPermission.h"
#import <UIKit/UIKit.h>
#import <objc/runtime.h>
#import <objc/message.h>
typedef void(^completionPermissionHandler)(BOOL granted,BOOL firstTime);
@implementation LBXPermission
+ (BOOL)isServicesEnabledWithType:(LBXPermissionType)type
{
if (type == LBXPermissionType_Location)
{
SEL sel = NSSelectorFromString(@"isServicesEnabled");
BOOL ret = ((BOOL *(*)(id,SEL))objc_msgSend)( NSClassFromString(@"LBXPermissionLocation"), sel);
return ret;
}
return YES;
}
+ (BOOL)isDeviceSupportedWithType:(LBXPermissionType)type
{
if (type == LBXPermissionType_Health) {
SEL sel = NSSelectorFromString(@"isHealthDataAvailable");
BOOL ret = ((BOOL *(*)(id,SEL))objc_msgSend)( NSClassFromString(@"LBXPermissionHealth"), sel);
return ret;
}
return YES;
}
+ (BOOL)authorizedWithType:(LBXPermissionType)type
{
SEL sel = NSSelectorFromString(@"authorized");
NSString *strClass = nil;
switch (type) {
case LBXPermissionType_Location:
strClass = @"LBXPermissionLocation";
break;
case LBXPermissionType_Camera:
strClass = @"LBXPermissionCamera";
break;
case LBXPermissionType_Photos:
strClass = @"LBXPermissionPhotos";
break;
case LBXPermissionType_Contacts:
strClass = @"LBXPermissionContacts";
break;
case LBXPermissionType_Reminders:
strClass = @"LBXPermissionReminders";
break;
case LBXPermissionType_Calendar:
strClass = @"LBXPermissionCalendar";
break;
case LBXPermissionType_Microphone:
strClass = @"LBXPermissionMicrophone";
break;
case LBXPermissionType_Health:
strClass = @"LBXPermissionHealth";
break;
case LBXPermissionType_DataNetwork:
break;
case LBXPermissionType_MediaLibrary:
strClass = @"LBXPermissionMediaLibrary";
break;
default:
break;
}
if (strClass) {
BOOL ret = ((BOOL *(*)(id,SEL))objc_msgSend)( NSClassFromString(strClass), sel);
return ret;
}
return NO;
}
+ (void)authorizeWithType:(LBXPermissionType)type completion:(void(^)(BOOL granted,BOOL firstTime))completion
{
NSString *strClass = nil;
switch (type) {
case LBXPermissionType_Location:
strClass = @"LBXPermissionLocation";
break;
case LBXPermissionType_Camera:
strClass = @"LBXPermissionCamera";
break;
case LBXPermissionType_Photos:
strClass = @"LBXPermissionPhotos";
break;
case LBXPermissionType_Contacts:
strClass = @"LBXPermissionContacts";
break;
case LBXPermissionType_Reminders:
strClass = @"LBXPermissionReminders";
break;
case LBXPermissionType_Calendar:
strClass = @"LBXPermissionCalendar";
break;
case LBXPermissionType_Microphone:
strClass = @"LBXPermissionMicrophone";
break;
case LBXPermissionType_Health:
strClass = @"LBXPermissionHealth";
break;
case LBXPermissionType_DataNetwork:
strClass = @"LBXPermissionData";
break;
case LBXPermissionType_MediaLibrary:
strClass = @"LBXPermissionMediaLibrary";
break;
default:
break;
}
if (strClass)
{
SEL sel = NSSelectorFromString(@"authorizeWithCompletion:");
((void(*)(id,SEL, completionPermissionHandler))objc_msgSend)(NSClassFromString(strClass),sel, completion);
}
}
@end

View File

@ -0,0 +1,18 @@
//
// LBXPermissionCamera.h
// LBXKits
//
#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>
@interface LBXPermissionCamera : NSObject
+ (BOOL)authorized;
+ (AVAuthorizationStatus)authorizationStatus;
+ (void)authorizeWithCompletion:(void(^)(BOOL granted ,BOOL firstTime ))completion;
@end

View File

@ -0,0 +1,71 @@
//
// LBXPermissionCamera.m
// LBXKits
//
#import "LBXPermissionCamera.h"
@implementation LBXPermissionCamera
+ (BOOL)authorized
{
if ([AVCaptureDevice respondsToSelector:@selector(authorizationStatusForMediaType:)])
{
AVAuthorizationStatus permission =
[AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
return permission == AVAuthorizationStatusAuthorized;
} else {
// Prior to iOS 7 all apps were authorized.
return YES;
}
}
+ (AVAuthorizationStatus)authorizationStatus
{
if ([AVCaptureDevice respondsToSelector:@selector(authorizationStatusForMediaType:)])
{
return [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
} else {
// Prior to iOS 7 all apps were authorized.
return AVAuthorizationStatusAuthorized;
}
}
+ (void)authorizeWithCompletion:(void(^)(BOOL granted,BOOL firstTime))completion
{
if ([AVCaptureDevice respondsToSelector:@selector(authorizationStatusForMediaType:)]) {
AVAuthorizationStatus permission =
[AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
switch (permission) {
case AVAuthorizationStatusAuthorized:
completion(YES,NO);
break;
case AVAuthorizationStatusDenied:
case AVAuthorizationStatusRestricted:
completion(NO,NO);
break;
case AVAuthorizationStatusNotDetermined:
{
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo
completionHandler:^(BOOL granted) {
if (completion) {
dispatch_async(dispatch_get_main_queue(), ^{
completion(granted,YES);
});
}
}];
}
break;
}
} else {
// Prior to iOS 7 all apps were authorized.
completion(YES,NO);
}
}
@end

View File

@ -0,0 +1,26 @@
//
// LBXPermissionPhotos.h
// LBXKits
//
#import <Foundation/Foundation.h>
@interface LBXPermissionPhotos : NSObject
+ (BOOL)authorized;
/**
photo permission status
@return
0 :NotDetermined
1 :Restricted
2 :Denied
3 :Authorized
*/
+ (NSInteger)authorizationStatus;
+ (void)authorizeWithCompletion:(void(^)(BOOL granted,BOOL firstTime))completion;
@end

View File

@ -0,0 +1,131 @@
//
// LBXPermissionPhotos.m
// LBXKits
//
#import "LBXPermissionPhotos.h"
#import <Photos/Photos.h>
#import <AssetsLibrary/AssetsLibrary.h>
@implementation LBXPermissionPhotos
+ (BOOL)authorized
{
return [self authorizationStatus] == 3;
}
/**
photo permission status
@return
0 :NotDetermined
1 :Restricted
2 :Denied
3 :Authorized
*/
+ (NSInteger)authorizationStatus
{
if (@available(iOS 8,*))
{
return [PHPhotoLibrary authorizationStatus];
}
else
{
return [ALAssetsLibrary authorizationStatus];
}
}
+ (void)authorizeWithCompletion:(void(^)(BOOL granted,BOOL firstTime))completion
{
if (@available(iOS 8.0, *)) {
PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];
switch (status) {
case PHAuthorizationStatusAuthorized:
{
if (completion) {
completion(YES,NO);
}
}
break;
case PHAuthorizationStatusRestricted:
case PHAuthorizationStatusDenied:
{
if (completion) {
completion(NO,NO);
}
}
break;
case PHAuthorizationStatusNotDetermined:
{
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
if (completion) {
dispatch_async(dispatch_get_main_queue(), ^{
completion(status == PHAuthorizationStatusAuthorized,YES);
});
}
}];
}
break;
default:
{
if (completion) {
completion(NO,NO);
}
}
break;
}
}else{
ALAuthorizationStatus status = [ALAssetsLibrary authorizationStatus];
switch (status) {
case ALAuthorizationStatusAuthorized:
{
if (completion) {
completion(YES, NO);
}
}
break;
case ALAuthorizationStatusNotDetermined:
{
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library enumerateGroupsWithTypes:ALAssetsGroupAll
usingBlock:^(ALAssetsGroup *assetGroup, BOOL *stop) {
if (*stop) {
if (completion) {
dispatch_async(dispatch_get_main_queue(), ^{
completion(YES, NO);
});
}
} else {
*stop = YES;
}
}
failureBlock:^(NSError *error) {
if (completion) {
dispatch_async(dispatch_get_main_queue(), ^{
completion(NO, YES);
});
}
}];
} break;
case ALAuthorizationStatusRestricted:
case ALAuthorizationStatusDenied:
{
if (completion) {
completion(NO, NO);
}
}
break;
}
}
}
@end

View File

@ -0,0 +1,51 @@
//
// LBXPermissionSetting.h
// Demo
//
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
API_AVAILABLE(ios(8.0))
@interface LBXPermissionSetting : NSObject
#pragma mark- guide user to show App privacy setting
/**
show App privacy settings
*/
+ (void)displayAppPrivacySettings;
/**
show dialog to guide user to show App privacy setting
@param title title
@param message privacy message
@param cancel cancel button text
@param setting setting button text,if user tap this button ,will show App privacy setting
*/
+ (void)showAlertToDislayPrivacySettingWithTitle:(NSString*)title
msg:(NSString*)message
cancel:(NSString*)cancel
setting:(NSString*)setting;
/**
show dialog to guide user to show App privacy setting
@param title title
@param message privacy message
@param cancel cancel button text
@param setting setting button text,if user tap this button ,will show App privacy setting
@param completion user has been choosed
*/
+ (void)showAlertToDislayPrivacySettingWithTitle:(NSString*)title
msg:(NSString*)message
cancel:(NSString*)cancel
setting:(NSString*)setting
completion:(void(^)(void))completion;
@end

View File

@ -0,0 +1,111 @@
//
// LBXPermissionSetting.m
// Demo
//
#import "LBXPermissionSetting.h"
#import <UIKit/UIKit.h>
@implementation LBXPermissionSetting
#pragma mark- disPlayAppPrivacySetting
+ (void)displayAppPrivacySettings
{
if (@available(iOS 8,*))
{
if (UIApplicationOpenSettingsURLString != NULL)
{
NSURL *appSettings = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
if (@available(iOS 10,*)) {
[[UIApplication sharedApplication]openURL:appSettings options:@{} completionHandler:^(BOOL success) {
}];
}
else
{
[[UIApplication sharedApplication]openURL:appSettings];
}
}
}
}
/**
show dialog to guide user to show App privacy setting
@param title title
@param message privacy message
@param cancel cancel button text
@param setting setting button text,if user tap this button ,will show App privacy setting
*/
+ (void)showAlertToDislayPrivacySettingWithTitle:(NSString*)title
msg:(NSString*)message
cancel:(NSString*)cancel
setting:(NSString*)setting
{
[self showAlertToDislayPrivacySettingWithTitle:title msg:message cancel:cancel setting:setting completion:nil];
}
/**
show dialog to guide user to show App privacy setting
@param title title
@param message privacy message
@param cancel cancel button text
@param setting setting button text,if user tap this button ,will show App privacy setting
@param completion user has been choosed
*/
+ (void)showAlertToDislayPrivacySettingWithTitle:(NSString*)title
msg:(NSString*)message
cancel:(NSString*)cancel
setting:(NSString*)setting
completion:(void(^)(void))completion
{
if (@available(iOS 8,*)) {
UIAlertController* alertController = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
//cancel
UIAlertAction *action = [UIAlertAction actionWithTitle:cancel style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
if (completion) {
completion();
}
}];
[alertController addAction:action];
//ok
UIAlertAction *okAction = [UIAlertAction actionWithTitle:setting style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
if (completion) {
completion();
}
[self displayAppPrivacySettings];
}];
[alertController addAction:okAction];
[[self currentTopViewController] presentViewController:alertController animated:YES completion:nil];
}
}
+ (UIViewController*)currentTopViewController
{
UIViewController *currentViewController = [UIApplication sharedApplication].delegate.window.rootViewController;
while ([currentViewController presentedViewController]) currentViewController = [currentViewController presentedViewController];
if ([currentViewController isKindOfClass:[UITabBarController class]]
&& ((UITabBarController*)currentViewController).selectedViewController != nil )
{
currentViewController = ((UITabBarController*)currentViewController).selectedViewController;
}
while ([currentViewController isKindOfClass:[UINavigationController class]]
&& [(UINavigationController*)currentViewController topViewController])
{
currentViewController = [(UINavigationController*)currentViewController topViewController];
}
return currentViewController;
}
@end

View File

@ -2,6 +2,8 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSPhotoLibraryUsageDescription</key>
<string>Restore Wallet recovery key need Photo Libray</string>
<key>CADisableMinimumFrameDuration</key>
<false/>
<key>CFBundleDevelopmentRegion</key>

View File

@ -79,10 +79,18 @@
D0DD4D8D8AC82F06A4331428 /* libil2cpp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 924940699744FB37428516DD /* libil2cpp.a */; };
D52A8DA1288E6547006574E8 /* libuv_a.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D52A8D9F288E6547006574E8 /* libuv_a.a */; };
D5538BA5287E9908000BDFB6 /* WalletEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D5538BA3287E9908000BDFB6 /* WalletEvent.cpp */; };
D579209F292F3C94004DBD4F /* LBXScanNative.m in Sources */ = {isa = PBXBuildFile; fileRef = D579209E292F3C94004DBD4F /* LBXScanNative.m */; };
D57920A2292F3D28004DBD4F /* LBXScanTypes.m in Sources */ = {isa = PBXBuildFile; fileRef = D57920A1292F3D28004DBD4F /* LBXScanTypes.m */; };
D57920A5292F4738004DBD4F /* QrCodeViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = D57920A4292F4738004DBD4F /* QrCodeViewController.xib */; };
D57920A8292F4763004DBD4F /* QrCodeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D57920A7292F4763004DBD4F /* QrCodeViewController.m */; };
D589C9BB28B62D93002CAA34 /* cacert.pem in Resources */ = {isa = PBXBuildFile; fileRef = D589C9B928B62D93002CAA34 /* cacert.pem */; };
D59AB424292DBACE00714392 /* CloudKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D59AB423292DBACE00714392 /* CloudKit.framework */; };
D59AB42F292E250500714392 /* UICKeyChainStore.m in Sources */ = {isa = PBXBuildFile; fileRef = D59AB42E292E250500714392 /* UICKeyChainStore.m */; };
D59AB433292E26CE00714392 /* DataManager.m in Sources */ = {isa = PBXBuildFile; fileRef = D59AB432292E26CE00714392 /* DataManager.m */; };
D59AB4AC292F325E00714392 /* LBXPermissionSetting.m in Sources */ = {isa = PBXBuildFile; fileRef = D59AB4A6292F325E00714392 /* LBXPermissionSetting.m */; };
D59AB4AD292F325E00714392 /* LBXPermissionPhotos.m in Sources */ = {isa = PBXBuildFile; fileRef = D59AB4A7292F325E00714392 /* LBXPermissionPhotos.m */; };
D59AB4AE292F325E00714392 /* LBXPermissionCamera.m in Sources */ = {isa = PBXBuildFile; fileRef = D59AB4A8292F325E00714392 /* LBXPermissionCamera.m */; };
D59AB4AF292F325E00714392 /* LBXPermission.m in Sources */ = {isa = PBXBuildFile; fileRef = D59AB4A9292F325E00714392 /* LBXPermission.m */; };
D5AB1D3328BF782300AA6AFA /* QRToggleTorchButton.m in Sources */ = {isa = PBXBuildFile; fileRef = D5AB1D2928BF782200AA6AFA /* QRToggleTorchButton.m */; };
D5AB1D3428BF782300AA6AFA /* QRCameraSwitchButton.m in Sources */ = {isa = PBXBuildFile; fileRef = D5AB1D2B28BF782200AA6AFA /* QRCameraSwitchButton.m */; };
D5AB1D3528BF782300AA6AFA /* QRCodeReaderViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D5AB1D2D28BF782200AA6AFA /* QRCodeReaderViewController.m */; };
@ -364,6 +372,13 @@
D52A8D9F288E6547006574E8 /* libuv_a.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libuv_a.a; sourceTree = "<group>"; };
D5538BA3287E9908000BDFB6 /* WalletEvent.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WalletEvent.cpp; sourceTree = "<group>"; };
D5538BA4287E9908000BDFB6 /* WalletEvent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WalletEvent.h; sourceTree = "<group>"; };
D579209C292F3C94004DBD4F /* LBXScanNative.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LBXScanNative.h; sourceTree = "<group>"; };
D579209E292F3C94004DBD4F /* LBXScanNative.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LBXScanNative.m; sourceTree = "<group>"; };
D57920A0292F3D28004DBD4F /* LBXScanTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LBXScanTypes.h; sourceTree = "<group>"; };
D57920A1292F3D28004DBD4F /* LBXScanTypes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LBXScanTypes.m; sourceTree = "<group>"; };
D57920A4292F4738004DBD4F /* QrCodeViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = QrCodeViewController.xib; sourceTree = "<group>"; };
D57920A6292F4763004DBD4F /* QrCodeViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = QrCodeViewController.h; sourceTree = "<group>"; };
D57920A7292F4763004DBD4F /* QrCodeViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = QrCodeViewController.m; sourceTree = "<group>"; };
D589C9B928B62D93002CAA34 /* cacert.pem */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = cacert.pem; sourceTree = "<group>"; };
D59AB422292DBABA00714392 /* Unity-iPhone.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = "Unity-iPhone.entitlements"; path = "Unity-iPhone/Unity-iPhone.entitlements"; sourceTree = "<group>"; };
D59AB423292DBACE00714392 /* CloudKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CloudKit.framework; path = System/Library/Frameworks/CloudKit.framework; sourceTree = SDKROOT; };
@ -371,6 +386,14 @@
D59AB42E292E250500714392 /* UICKeyChainStore.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UICKeyChainStore.m; sourceTree = "<group>"; };
D59AB431292E26B600714392 /* DataManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DataManager.h; sourceTree = "<group>"; };
D59AB432292E26CE00714392 /* DataManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DataManager.m; sourceTree = "<group>"; };
D59AB4A4292F325E00714392 /* LBXPermission.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LBXPermission.h; sourceTree = "<group>"; };
D59AB4A5292F325E00714392 /* LBXPermissionCamera.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LBXPermissionCamera.h; sourceTree = "<group>"; };
D59AB4A6292F325E00714392 /* LBXPermissionSetting.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LBXPermissionSetting.m; sourceTree = "<group>"; };
D59AB4A7292F325E00714392 /* LBXPermissionPhotos.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LBXPermissionPhotos.m; sourceTree = "<group>"; };
D59AB4A8292F325E00714392 /* LBXPermissionCamera.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LBXPermissionCamera.m; sourceTree = "<group>"; };
D59AB4A9292F325E00714392 /* LBXPermission.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LBXPermission.m; sourceTree = "<group>"; };
D59AB4AA292F325E00714392 /* LBXPermissionPhotos.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LBXPermissionPhotos.h; sourceTree = "<group>"; };
D59AB4AB292F325E00714392 /* LBXPermissionSetting.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LBXPermissionSetting.h; sourceTree = "<group>"; };
D5AB1D2828BF782200AA6AFA /* QRCodeReaderView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QRCodeReaderView.h; sourceTree = "<group>"; };
D5AB1D2928BF782200AA6AFA /* QRToggleTorchButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QRToggleTorchButton.m; sourceTree = "<group>"; };
D5AB1D2A28BF782200AA6AFA /* QRCodeReaderDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QRCodeReaderDelegate.h; sourceTree = "<group>"; };
@ -759,6 +782,20 @@
path = Pods;
sourceTree = "<group>";
};
D57920A3292F45D3004DBD4F /* qr */ = {
isa = PBXGroup;
children = (
D579209C292F3C94004DBD4F /* LBXScanNative.h */,
D579209E292F3C94004DBD4F /* LBXScanNative.m */,
D57920A0292F3D28004DBD4F /* LBXScanTypes.h */,
D57920A1292F3D28004DBD4F /* LBXScanTypes.m */,
D57920A6292F4763004DBD4F /* QrCodeViewController.h */,
D57920A7292F4763004DBD4F /* QrCodeViewController.m */,
D57920A4292F4738004DBD4F /* QrCodeViewController.xib */,
);
name = qr;
sourceTree = "<group>";
};
D59AB434292E389E00714392 /* KeyChain */ = {
isa = PBXGroup;
children = (
@ -770,6 +807,21 @@
path = KeyChain;
sourceTree = "<group>";
};
D59AB4A3292F325E00714392 /* permission */ = {
isa = PBXGroup;
children = (
D59AB4A4292F325E00714392 /* LBXPermission.h */,
D59AB4A5292F325E00714392 /* LBXPermissionCamera.h */,
D59AB4A6292F325E00714392 /* LBXPermissionSetting.m */,
D59AB4A7292F325E00714392 /* LBXPermissionPhotos.m */,
D59AB4A8292F325E00714392 /* LBXPermissionCamera.m */,
D59AB4A9292F325E00714392 /* LBXPermission.m */,
D59AB4AA292F325E00714392 /* LBXPermissionPhotos.h */,
D59AB4AB292F325E00714392 /* LBXPermissionSetting.h */,
);
path = permission;
sourceTree = "<group>";
};
D5AB1D2728BF782200AA6AFA /* QRCodeReaderViewController */ = {
isa = PBXGroup;
children = (
@ -904,6 +956,7 @@
D5F2CFAB287BF3BD003C2B62 /* Classes_cocos */ = {
isa = PBXGroup;
children = (
D59AB4A3292F325E00714392 /* permission */,
D5F2CFAE287BF3BD003C2B62 /* NativeConfig.h */,
D5F2CFAC287BF3BD003C2B62 /* AppDelegate.h */,
D5F2CFAF287BF3BD003C2B62 /* AppDelegate.mm */,
@ -913,6 +966,7 @@
D5F2D104287C12DD003C2B62 /* JcWallet.mm */,
D5538BA4287E9908000BDFB6 /* WalletEvent.h */,
D5538BA3287E9908000BDFB6 /* WalletEvent.cpp */,
D57920A3292F45D3004DBD4F /* qr */,
D59AB434292E389E00714392 /* KeyChain */,
);
path = Classes_cocos;
@ -1083,6 +1137,7 @@
7885412B8F5A921FCB052FCC /* LaunchScreen-iPhoneLandscape.png in Resources */,
B39C4391A8C22B442413FE00 /* LaunchScreen-iPad.xib in Resources */,
C7134CE09546D0C147DAA3D3 /* LaunchScreen-iPad.png in Resources */,
D57920A5292F4738004DBD4F /* QrCodeViewController.xib in Resources */,
D5F2CED6287BE9C4003C2B62 /* Data in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -1177,6 +1232,7 @@
D5F2CFA6287BEC0D003C2B62 /* Bulk_netstandard_0.cpp in Sources */,
D5F2CF53287BEC0D003C2B62 /* GenericMethods0.cpp in Sources */,
D5AB1D3628BF782300AA6AFA /* QRCodeReaderView.m in Sources */,
D59AB4AC292F325E00714392 /* LBXPermissionSetting.m in Sources */,
D5F2CF95287BEC0D003C2B62 /* Bulk_mscorlib_12.cpp in Sources */,
D5F2CF87287BEC0D003C2B62 /* Bulk_UnityEngine.CoreModule_1.cpp in Sources */,
D82DCFC30E8000A5005D6AD8 /* main.mm in Sources */,
@ -1237,6 +1293,7 @@
D5F2CF49287BEC0D003C2B62 /* UnityICallRegistration.cpp in Sources */,
D5F2CF65287BEC0D003C2B62 /* Bulk_mscorlib_5.cpp in Sources */,
848031E11C5160D700FCEAB7 /* UnityReplayKit_Scripting.mm in Sources */,
D59AB4AD292F325E00714392 /* LBXPermissionPhotos.m in Sources */,
D5F2CF94287BEC0D003C2B62 /* Bulk_Generics_9.cpp in Sources */,
D5F2CF52287BEC0D003C2B62 /* Il2CppCompilerCalculateTypeValues_16Table.cpp in Sources */,
D5F2CF91287BEC0D003C2B62 /* Bulk_mscorlib_10.cpp in Sources */,
@ -1271,6 +1328,7 @@
D59AB42F292E250500714392 /* UICKeyChainStore.m in Sources */,
D5F2CF90287BEC0D003C2B62 /* Il2CppCompilerCalculateTypeValues_6Table.cpp in Sources */,
D5F2CFA8287BEC0D003C2B62 /* Il2CppCompilerCalculateTypeValues_13Table.cpp in Sources */,
D59AB4AF292F325E00714392 /* LBXPermission.m in Sources */,
D5F2CF5C287BEC0D003C2B62 /* Bulk_Generics_7.cpp in Sources */,
8A793A091ED43EE100B44EF1 /* UnityViewControllerBase+tvOS.mm in Sources */,
D5F2CF58287BEC0D003C2B62 /* Il2CppGenericMethodPointerTable.cpp in Sources */,
@ -1282,8 +1340,10 @@
D5F2CFA2287BEC0D003C2B62 /* Bulk_System.Globalization.Extensions_0.cpp in Sources */,
D5F2CF77287BEC0D003C2B62 /* Bulk_Generics_10.cpp in Sources */,
D5F2CF44287BEC0D003C2B62 /* Il2CppCompilerCalculateTypeValues_9Table.cpp in Sources */,
D57920A8292F4763004DBD4F /* QrCodeViewController.m in Sources */,
D5F2CF6B287BEC0D003C2B62 /* Bulk_mscorlib_3.cpp in Sources */,
D5F2CF92287BEC0D003C2B62 /* Bulk_System.Configuration_0.cpp in Sources */,
D57920A2292F3D28004DBD4F /* LBXScanTypes.m in Sources */,
D5AB1D3728BF782300AA6AFA /* QRCodeReader.m in Sources */,
D5F2CF9D287BEC0D003C2B62 /* Il2CppCompilerCalculateTypeValues_19Table.cpp in Sources */,
D5F2CF61287BEC0D003C2B62 /* Bulk_mscorlib_6.cpp in Sources */,
@ -1292,6 +1352,7 @@
D5F2CF62287BEC0D003C2B62 /* Bulk_mscorlib_7.cpp in Sources */,
8A4815C117A28E7F003FBFD5 /* UnityAppController+ViewHandling.mm in Sources */,
D5F2D106287C12DD003C2B62 /* JcWallet.mm in Sources */,
D579209F292F3C94004DBD4F /* LBXScanNative.m in Sources */,
D5F2CF8B287BEC0D003C2B62 /* Bulk_System.Diagnostics.StackTrace_0.cpp in Sources */,
D5F2CF63287BEC0D003C2B62 /* Il2CppCompilerCalculateTypeValues_10Table.cpp in Sources */,
D5F2CF88287BEC0D003C2B62 /* Bulk_UnityEngine.UIModule_0.cpp in Sources */,
@ -1315,6 +1376,7 @@
D5F2CF69287BEC0D003C2B62 /* Bulk_mscorlib_1.cpp in Sources */,
D5F2CF55287BEC0D003C2B62 /* Il2CppCompilerCalculateTypeValues_23Table.cpp in Sources */,
D5F2CF66287BEC0D003C2B62 /* Bulk_mscorlib_4.cpp in Sources */,
D59AB4AE292F325E00714392 /* LBXPermissionCamera.m in Sources */,
AAC3E38D1A68945900F6174A /* RegisterFeatures.cpp in Sources */,
84DC28F61C5137FE00BC67D7 /* UnityReplayKit.mm in Sources */,
D5F2CF73287BEC0D003C2B62 /* Bulk_System_0.cpp in Sources */,
@ -1381,6 +1443,7 @@
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_CPP_EXCEPTIONS = YES;
GCC_ENABLE_CPP_RTTI = YES;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = Classes/Prefix.pch;
@ -1468,6 +1531,7 @@
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
GCC_ENABLE_CPP_EXCEPTIONS = YES;
GCC_ENABLE_CPP_RTTI = YES;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = Classes/Prefix.pch;
HEADER_SEARCH_PATHS = (
@ -1683,6 +1747,7 @@
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
GCC_ENABLE_CPP_EXCEPTIONS = YES;
GCC_ENABLE_CPP_RTTI = YES;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = Classes/Prefix.pch;
HEADER_SEARCH_PATHS = (
@ -1840,6 +1905,7 @@
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
GCC_ENABLE_CPP_EXCEPTIONS = YES;
GCC_ENABLE_CPP_RTTI = YES;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = Classes/Prefix.pch;
HEADER_SEARCH_PATHS = (

View File

@ -12,11 +12,11 @@
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "Classes_cocos/UIViewController+Wallet.mm"
startingColumnNumber = "9"
endingColumnNumber = "9"
startingLineNumber = "133"
endingLineNumber = "133"
landmarkName = "-refreshTokenID:funid:"
startingColumnNumber = "11"
endingColumnNumber = "11"
startingLineNumber = "107"
endingLineNumber = "107"
landmarkName = "-scanQRCode:title:"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
@ -30,9 +30,9 @@
filePath = "Classes_cocos/UIViewController+Wallet.mm"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "131"
endingLineNumber = "131"
landmarkName = "-refreshTokenID:funid:"
startingLineNumber = "105"
endingLineNumber = "105"
landmarkName = "-scanQRCode:title:"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
@ -46,28 +46,12 @@
filePath = "Classes_cocos/UIViewController+Wallet.mm"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "133"
endingLineNumber = "133"
landmarkName = "-refreshTokenID:funid:"
startingLineNumber = "107"
endingLineNumber = "107"
landmarkName = "-scanQRCode:title:"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "15F1FD11-897D-4AA2-89F0-86DCB06070A1"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "Classes_cocos/JcWallet.mm"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "189"
endingLineNumber = "189"
landmarkName = "nativeCallBack(funId, methodName, cparams)"
landmarkType = "9">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
@ -78,9 +62,9 @@
filePath = "Classes_cocos/UIViewController+Wallet.mm"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "132"
endingLineNumber = "132"
landmarkName = "-refreshTokenID:funid:"
startingLineNumber = "106"
endingLineNumber = "106"
landmarkName = "-scanQRCode:title:"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
@ -94,25 +78,9 @@
filePath = "Classes_cocos/UIViewController+Wallet.mm"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "138"
endingLineNumber = "138"
landmarkName = "-signWithGoogle:"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "4D1CEFCB-9F08-4069-BC1B-9139709C217E"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "Classes_cocos/JcWallet.mm"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "135"
endingLineNumber = "135"
landmarkName = "JcWallet::runJsMethod(data)"
startingLineNumber = "112"
endingLineNumber = "112"
landmarkName = "-scanQRCode:title:"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
@ -132,5 +100,101 @@
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "47347B45-DB23-4252-AFCD-8D070482488B"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "Classes_cocos/UIViewController+Wallet.mm"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "65"
endingLineNumber = "65"
landmarkName = "-scanQRCode:title:"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "DF8812E4-AA7D-42CD-BA48-816CB6377C98"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "Classes_cocos/UIViewController+Wallet.mm"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "70"
endingLineNumber = "70"
landmarkName = "-scanQRCode:title:"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "6DA3708B-7F80-4969-83A7-4AE84264C340"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "Classes_cocos/UIViewController+Wallet.mm"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "64"
endingLineNumber = "64"
landmarkName = "-scanQRCode:title:"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "5228CC88-A530-4590-BFE9-CB7361B45F34"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "Classes_cocos/JcWallet.mm"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "205"
endingLineNumber = "205"
landmarkName = "runWalletMethod(funId, methodName, paramCount, paramList)"
landmarkType = "9">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "DED33FE0-B995-4059-9A5A-1A41F1F988B4"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "Classes_cocos/JcWallet.mm"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "169"
endingLineNumber = "169"
landmarkName = "JcWallet::tickRun()"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "4418B859-58DC-425E-B856-48D07E6F9315"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "Classes_cocos/JcWallet.mm"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "272"
endingLineNumber = "272"
landmarkName = "jsb_wallet_callback(s)"
landmarkType = "9">
</BreakpointContent>
</BreakpointProxy>
</Breakpoints>
</Bucket>

View File

@ -1,3 +1,4 @@
window.self = window.self || window;
(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
(function (global){
"use strict";

View File

@ -125,6 +125,7 @@ function changeChain(funId, chainId) {
* @param {string} tips: tips message when sign
*/
function loginSign(funId, nonce, tips) {
console.log('login sign: ' + funId)
jc.wallet
.loginSign(nonce, tips)
.then((result) => {
@ -163,18 +164,21 @@ function createAccount(funId) {
* @return {string} account actived
*/
function importAccount(funId, privateKey) {
try {
let address = jc.wallet.importAccount(privateKey);
return JSON.stringify({
errcode: 0,
data: address,
});
} catch (err) {
return JSON.stringify({
errcode: 1,
errmsg: err,
});
}
console.log('importAccount: ' + funId);
// jsb.scanQRCode(funId, '111');
jsb.showQRCode('00123', '0x12312312313123123123', 'CEBG RECOVERY KEY', '0x1231231231321231');
// try {
// let address = jc.wallet.importAccount(privateKey);
// return JSON.stringify({
// errcode: 0,
// data: address,
// });
// } catch (err) {
// return JSON.stringify({
// errcode: 1,
// errmsg: err,
// });
// }
// jc.wallet.erc20Standard.transfer({
// address: '0xC76c692450d6221A8B1E035CB8bdB639bC60658D',
// from: '0x50A8e60041A206AcaA5F844a1104896224be6F39',