IOS-二维码的实现
如今二维码随处可见,无论是实物商品还是各种礼券都少不了二维码的身影。而手机等移动设备又成为二维码的一个很好的应用平台,不管是生成二维码还是扫码二维码。
下面介绍一下如何在苹果iOS设备上使用二维码:
1. 二维码的生成
#import "NSString+Helper.h"
// 加入框架
#import <CoreImage/CoreImage.h>
@implementation NSString (Helper)
/**
返回当前字符串对应的二维码图像
二维码的实现是将字符串传递给滤镜,滤镜直接转换生成二维码图片
*/
- (UIImage *)createQRCode
{
// 1. 实例化一个滤镜
CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
// 1.1 设置filter的默认值
// 因为之前如果使用过滤镜,输入有可能会被保留,因此,在使用滤镜之前,最好设置恢复默认值
[filter setDefaults];
// 2. 将传入的字符串转换为NSData
NSData *data = [self dataUsingEncoding:NSUTF8StringEncoding];
// 3. 将NSData传递给滤镜(通过KVC的方式,设置inputMessage)
[filter setValue:data forKey:@"inputMessage"];
// 4. 由filter输出图像
CIImage *outputImage = [filter outputImage];
// 5. 将CIImage转换为UIImage
return [UIImage imageWithCIImage:outputImage];
}
@end
2. 二维码的读取
#import "ViewController.h"
#import <AVFoundation/AVFoundation.h>
@interface ViewController () <AVCaptureMetadataOutputObjectsDelegate>
@property (weak, nonatomic) IBOutlet UILabel *label;
@property (strong, nonatomic) AVCaptureSession *session;
@property (strong, nonatomic) AVCaptureVideoPreviewLayer *previewLayer;
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
}
#pragma mark - 读取二维码
- (void)readQRCoder
{
// 1. 摄像头设备
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
// 2. 设置输入
// 因为模拟器是没有摄像头的,因此在此最好做一个判断
NSError *error = nil;
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
if (error) {
NSLog(@"没有摄像头-%@", error.localizedDescription);
return;
}
// 3. 设置输出(Metadata元数据)
AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc] init];
// 3.1 设置输出的代理
// 说明:使用主线程队列,相应比较同步,使用其他队列,相应不同步,容易让用户产生不好的体验
[output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
// [output setMetadataObjectsDelegate:self queue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)];
// 4. 拍摄会话
AVCaptureSession *session = [[AVCaptureSession alloc] init];
// 添加session的输入和输出
[session addInput:input];
[session addOutput:output];
// 4.1 设置输出的格式
// 提示:一定要先设置会话的输出为output之后,再指定输出的元数据类型!
[output setMetadataObjectTypes:@[AVMetadataObjectTypeQRCode]];
// 5. 设置预览图层(用来让用户能够看到扫描情况)
AVCaptureVideoPreviewLayer *preview = [AVCaptureVideoPreviewLayer layerWithSession:session];
// 5.1 设置preview图层的属性
[preview setVideoGravity:AVLayerVideoGravityResizeAspectFill];
// 5.2 设置preview图层的大小
[preview setFrame:self.view.bounds];
// 5.3 将图层添加到视图的图层
[self.view.layer insertSublayer:preview atIndex:0];
self.previewLayer = preview;
// 6. 启动会话
[session startRunning];
self.session = session;
}
#pragma mark - 输出代理方法
// 此方法是在识别到QRCode,并且完成转换
// 如果QRCode的内容越大,转换需要的时间就越长
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
{
// 会频繁的扫描,调用代理方法
// 1. 如果扫描完成,停止会话
[self.session stopRunning];
// 2. 删除预览图层
[self.previewLayer removeFromSuperlayer];
NSLog(@"%@", metadataObjects);
// 3. 设置界面显示扫描结果
if (metadataObjects.count > 0) {
AVMetadataMachineReadableCodeObject *obj = metadataObjects[0];
// 提示:如果需要对url或者名片等信息进行扫描,可以在此进行扩展!
_label.text = obj.stringValue;
}
}
- (IBAction)capture
{
[self readQRCoder];
}
@end