ios 二维码界面和代码实现,优化卡顿
https://www.cnblogs.com/pretty-guy/p/4255359.html
原理:
AVCaptureSession 管理者
input 读取 二维码
output输出 二维码的内容
AVCaptureVideoPreviewLayer 界面
代理方法输出字符串。
逻辑
1.判断相机,以及拒绝打开相机的操作
https://www.jianshu.com/p/c71c12da3bb1
2
界面
导航条透明,状态栏白色,返回按钮白色:
viewWillAppear设置,
viewwilldisappear 重新设置为正常;
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
[self.navigationController.navigationBar setTranslucent:YES];//设置透明度
// //颜色字体
self.navigationController.navigationBar.titleTextAttributes = @{NSForegroundColorAttributeName:kWhiteColor,NSFontAttributeName:[UIFont boldSystemFontOfSize:17]};
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setImage:[UIImage imageNamed:@"icon_back"] forState:UIControlStateNormal];
button.size = CGSizeMake(70, 44);
[button setImageEdgeInsets:UIEdgeInsetsMake(5, 5, 5, 0)];//上左下右
button.imageView.contentMode = UIViewContentModeScaleAspectFit;
button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
[button addTarget:self action:@selector(backBtn) forControlEvents:UIControlEventTouchUpInside];
//这个地方就是self.navigationItem,不是controuler,好像是系统的,上边的那个返回图片无效,有空在考虑原因。
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
//状态栏
//1.在info.plist中添加View controller-based status bar appearance,值为NO
[UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent;
}
- (void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
[self.navigationController.navigationBar setTranslucent:NO];//设置透明度
[UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleDefault;//状态栏
//颜色字体
self.navigationController.navigationBar.titleTextAttributes = @{NSForegroundColorAttributeName:kNavTitleColor,NSFontAttributeName:[UIFont boldSystemFontOfSize:17]};
}
扫描线:
动画有个属性UIViewAnimationOptionRepeat是反复执行的意思
//还有一种是加timer的,也是要设置,进入后台timer不停的。
_line.frame = CGRectMake(0, 0, scanSize.width, 18);//扫描线的imageview
/* 添加动画 */
[UIView animateWithDuration:2.5 delay:0.0 options:UIViewAnimationOptionRepeat animations:^{//反复执行
_line.frame = CGRectMake(0, scanSize.height-18, scanSize.width, 10);
} completion:nil];
动画进入后台之后会消失.那么就让它进入激活状态重新打开动画
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appDidEnterPlayground) name:UIApplicationDidBecomeActiveNotification object:nil];
}
-(void)appDidEnterPlayground{
[self.heroBtn.layer removeAllAnimations];//移除动画
[self.heroBtn.layer addAnimation:[self groupAnimation] forKey:nil];//添加动画
}
但是这样的话,只要app进过的二维码的界面,已有不管在那个地方,只要重新进入前端都会刷新一下这个动画。挺尴尬,未完待续。
卡顿
这里二维码相关的设置设置完以后我们就要启动扫描了,这里一般是直接调方法 [self.captureSession startRunning]来开始扫描,但问题就在这里,这个方法是会阻塞主线程的直到启动完成,api说明里是有注明的,所以我们就不能这样用,会照成卡顿,我们要放到子线程去启动就行了,顺便做一个加载动画,跟微信的做法保持一致
时间有限,动画就不做了,下面链接里有
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{//
[[KJZbar manager] startRunning];
// [_kBar startRunning];
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[[KJZbar manager] stopRunning];
});
https://blog.csdn.net/weixin_33670786/article/details/87133426
//下面的删了。出现在连续两个界面都是背景透明的情况会很卡,但是这个东西,需求删掉了。
写到子线程中,界面不卡了,背景延迟,才出来,于是把二维码做成单利,好多了
+ (id)manager{
static KJZbar * singleton = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
singleton = [[KJZbar alloc] init];
});
return singleton;
// DLZBar * singleton;
// singleton = [[DLZBar alloc] init];
// return singleton;
}
ios 打开关闭手电筒
//yes 开, no是关
- (void)turnTorchOn:(bool)on{
Class captureDeviceClass = NSClassFromString(@"AVCaptureDevice");
if (captureDeviceClass != nil) {
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
if ([device hasTorch] && [device hasFlash]){
[device lockForConfiguration:nil];
if (on) {
[device setTorchMode:AVCaptureTorchModeOn];
[device setFlashMode:AVCaptureFlashModeOn];
on = YES;
} else {
[device setTorchMode:AVCaptureTorchModeOff];
[device setFlashMode:AVCaptureFlashModeOff];
on = NO;
}
[device unlockForConfiguration];
}
}
}
如果要在多个界面打开手电,写一个block回调,执行viewDidAppear。willAppear打不开手电。
- (void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
//手电筒的回调
if (_lightState) {
[self turnTorchOn:YES];
}else{
[self turnTorchOn:NO];
}
}