前言
二维码每个人都一定不陌生 尤其是在支付宝和微信的努力下 相信每个人都或多或少的使用过”扫一扫”这个功能
而作为开发者 大家都应该有过二维码的开发经验 不管是练习还是研究 或者是公司的项目(尤其是社交类的APP 基本都有扫一扫加好友这个功能吧?)
介绍
说到二维码 其实我们现在生活中接触到的都是QRCode —由日本人在上个世纪末用于汽车工业的一项发明 如今在移动互联网发光发亮
而实际上 除了QRCode 还有很多二维码的类型 最出名的应该就是DataMatrix了 而在4,5年前 一度还有很多QRCode的竞争对手出现 比如微软推出的Microsoft Tag 还有个人觉得很有意思的SnapTag 可是在这几年的发展过程中 还是QRCode笑到了最后 所以现在我们一般提起二维码 就指的是QRCode 下面我们就用QRCode来代替二维码
对于开发人员来说 熟悉的第三方QRCode库有:
而我从开始到现在一直是ZXing的忠实用户 除了Google的光环之外 那时候的ZXing资料也比ZBar多很多 不过随着iOS7的发布 苹果推出了内建的二维码扫描功能 这让这些第三方库多少显得有点尴尬了
回到今天的主题上 为什么说要跟ZXing说再见呢? 其实我目前做的项目使用的也是ZXing 不过在开发过程中发现了一些很严重而且绕不过去的问题 比如下面这张图此处输入图片的描述
如果使用相册读取QRCode的功能 ZXing是无法识别的 不信大家可以去zxing.org 我也去Github提了issue 不过作者也没有给出有效的解决办法 所以只能跟ZXing说88了(不过ZBar是可以扫描出来的哟!)
先分析一下 我们使用QRCode一般都是要做如下几种场景的操作
- 扫描
比如 微信的”扫一扫“加好友- 读取
比如 微信中长按图片 会弹出”识别图中二维码“这个功能- 生成
比如 微信的”我的二维码“功能
接下来我们就分三个部分分别来介绍一下如何实现对应的功能(要注意的是 “读取图片“这个功能只有在iOS8以上的系统才能支持 iOS7的话 建议还是使用ZXing或者ZBar)
扫描
扫描主要使用的是AVFoundation 使用起来也非常的简单 正常的初始化流程如下
1
|
@interface Example1Controller()
|
AVFoundation的部分我就不多介绍了 只要按照上面的代码初始化 即可实现二维码扫描的功能 是不是很简单?
不过这里还不能完全满足我们的要求 因为如果运行以后你会发现 现在是全屏扫描 而不是像我们印象中的那种在屏幕中间有个框 只有在框中的二维码才会被扫描到 不过其实改起来也很简单 AVCaptureMetadataOutput有个属性rectOfInterest
就是做这个事情的
1
|
@interface AVCaptureMetadataOutput : AVCaptureOutput
|
可以看到 rectOfInterest
的值的范围都是0-1 是按比例取值而不是实际尺寸 不过其实也很简单 只要换算一下就好了 接下来我们添加取景框
1
|
CGSize windowSize = [UIScreen mainScreen].bounds.size;
|
这里唯一要注意的一点是 rectOfInterest 都是按照横屏来计算的 所以当竖屏的情况下 x轴和y轴要交换一下
读取
读取主要用到CoreImage 不过要强调的是读取二维码的功能只有在iOS8之后才支持
读取的代码实现就更简单了
1
|
UIImage * srcImage = qrcodeImage;
|
生成
生成也是用到CoreImage 其步骤稍微多一点 代码如下
1
|
NSString *text = self.tfCode.text;
|
- 首先通过
[CIFilter filterWithName:@"CIQRCodeGenerator"]
生成QRCode - 然后通过
[CIFilter filterWithName:@"CIFalseColor"]
上色(当然这一步不是必须的 如果仅仅需要白底黑块的QRCode 可以跳过这一步) - 最后无损放大并绘制QRCode (上面两步生成的QRCode很小 大概是31*31 如果不放大 就会很模糊)
这里要注意的是 在最后一步一定要使用CGContextScaleCTM(context, 1.0, -1.0)
来翻转一下图片 不然生成的QRCode就是上下颠倒的哦
小结
源码和Demo请点这里
如果不需要对QRCode进行深入的探索的话 相信各位看完本文后 绝大多数的关于QRCode的使用问题 应该都可以迎刃而解了 如果需要进一步了解QRCode的原理 我推荐陈皓的这篇二维码的生成细节和原理