摄像头扫描二维码
Info.plist 配置
由于苹果安全策略更新,在使用 Xcode8 开发时,需要在 Info.plist 配置请求摄像头的相关描述字段(Privacy - Camera Usage Description)
在主视图ViewController中
添加一个button 给这个button加上点击事件用来跳转到扫一扫页面
在摄像头视图view2中
导入头文件 import AVFoundation 获取摄像设备
主要方法介绍:
AVCaptureSession 管理输入(AVCaptureInput)和输出(AVCaptureOutput)流,包含开启和停止会话方法。
AVCaptureDeviceInput 是AVCaptureInput的子类,可以作为输入捕获会话,用AVCaptureDevice实例初始化。
AVCaptureDevice代表了物理捕获设备如:摄像机。用于配置等底层硬件设置相机的自动对焦模式。
AVCaptureMetadataOutput是AVCaptureOutput的子类,处理输出捕获会话。捕获的对象传递给一个委托实现AVCaptureMetadataOutputObjectsDelegate协议。协议方法在指定的派发队列(dispatch queue)上执行。
AVCaptureVideoPreviewLayerCALayer的一个子类,显示捕获到的相机输出流。
定义以上变量。
下一步定义一个与storyboard关联的函数 fromcamera(任意名)
@IBAction func fromCamera(_ sender: AnyObject){
//print("调用扫一扫功成功")。调试语句
do{
self.device = AVCaptureDevice.default(for: AVMediaType.video)
//调用摄像头
self.input = try AVCaptureDeviceInput(device: device)
//创建输入流 如果没有检测到设备则执行try catch语句
self.output = AVCaptureMetadataOutput()
//创建捕获输出流
output.setMetadataObjectsDelegate(self as AVCaptureMetadataOutputObjectsDelegate, queue: DispatchQueue.main)
//处理输出捕获会话协议 协议方法在指定的派发队列(DispatchQueue queue)上执行。 实现方法
self.session = AVCaptureSession()
//创建会话
if UIScreen.main.bounds.size.height<500{
self.session.sessionPreset = AVCaptureSession.Preset.vga640x480
// 如果 设备的高小于500?
//则摄像头捕捉的大小为640*480?
}else{
self.session.sessionPreset = AVCaptureSession.Preset.high
//否则将检测到的高赋值给sessionPreset
}
self.session.addInput(self.input)
//加入到输入流
self.session.addOutput(self.output)
//加入到输出流
self.output.metadataObjectTypes = [AVMetadataObject.ObjectType.qr]
//将读码功能给output
let windowSize = UIScreen.main.bounds.size
//获取屏幕的大小
let scanSize = CGSize(width:windowSize.width*2/3, height:windowSize.width*2/3)
//使用scanSize来保存windowSize的当前宽高
var scanRect = CGRect(x:(windowSize.width-scanSize.width)/2,//用scanRect来保持矩形当前的位置和大小 x:扫描框的第一个x坐标
y:(windowSize.height-scanSize.height)/2,// y:扫描框的第一个y坐标
width:scanSize.width,height:scanSize.height)// x:扫描框的大小
//执行多一次转换成rectOfInterest认识的参数
scanRect = CGRect(x:scanRect.origin.y/windowSize.height,
y:scanRect.origin.x/windowSize.width,
width:scanRect.size.height/windowSize.height,
height:scanRect.size.width/windowSize.width);
//实现背景虚化
print(scanRect)
background()
//设置可探测区域
self.output.rectOfInterest = scanRect
self.preview = AVCaptureVideoPreviewLayer(session:self.session)
//扫描到宽高
self.preview.videoGravity = AVLayerVideoGravity.resizeAspectFill
//定义摄像头则图层边界矩形内显示的宽高?
self.preview.frame = UIScreen.main.bounds
//摄像头获取到的大小。 占满屏幕
self.view.layer.insertSublayer(self.preview, at: 0)
//将它插入子图层
//添加中间的探测区域绿框
self.scanRectview = UIView();
//创建 一个视图
self.view.addSubview(self.scanRectview)
//将它加入到view中
self.scanRectview.frame = CGRect(x:0,y:0,width:scanSize.width,
height:scanSize.height);
//居中
self.scanRectview.center = CGPoint(x:UIScreen.main.bounds.midX,
y:UIScreen.main.bounds.midY)
//边框的颜色
self.scanRectview.layer.borderColor = UIColor.white.cgColor
//边框的宽度
self.scanRectview.layer.borderWidth = 1;
//添加yyy
// let juxing = UIView(frame:CGRect(x:(scanRect.origin.y/windowSize.height),//获取第二个x的坐标
// y:scanRect.origin.x/windowSize.width,//获取第二个y的坐标
// width:scanRect.size.height/windowSize.height,
// height:scanRect.size.width/windowSize.width));
// juxing.backgroundColor = UIColor.red
// self.view.addSubview(juxing)
//
//开始捕获
self.session.startRunning()
}catch _{
print("失败lo")
//捕捉失败后执行弹框提示
let alertController = UIAlertController(title:"提醒",
message:"请在iphone的\"设置-隐私-相机\"选项中,允许本程序访问相机",
preferredStyle:.alert)
let cancelAction = UIAlertAction(title:"确定",style:.cancel,handler:nil)
alertController.addAction(cancelAction)
self.present(alertController,animated: true,completion: nil)
}
func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
//定义一个stringValue来保存捕捉到的信息
var stringValue:String?
if metadataObjects.count > 0{
let metadataObject = metadataObjects[0] as! AVMetadataMachineReadableCodeObject
stringValue = metadataObject.stringValue
//解析结果
print(stringValue)
if stringValue != nil{
self.session.startRunning()
}
}
self.session.stopRunning()
//判断结果是否为有效网址
//如果为有效网址则用wkview打开
//否则用弹窗的形式将其显示出来
if let urll = URL(string: stringValue!){
if UIApplication.shared.canOpenURL(urll){
wkview(urll: stringValue!)
}else{
alertfun(stringvalue: stringValue!)
}
}else{
alertfun(stringvalue: stringValue!)
}
}
@objc func alertfun(stringvalue: String){
let alertController = UIAlertController(title:"二维码",
message:stringvalue,preferredStyle:.alert)
let okAction = UIAlertAction(title:"确定",style:.default,handler:{
action in
self.session.startRunning()
})
alertController.addAction(okAction)
self.present(alertController,animated: true,completion: nil)
}
@objc func wkview(urll: String){
let wkwebview = WKWebViewConfiguration()
let myURL = URL(string:urll)
let webview = WKWebView(frame:view.bounds,configuration:wkwebview)
let myRequest = URLRequest(url:myURL!)
webview.load(myRequest)
view.addSubview(webview)
print("加载完毕")
}
}
效果图:(真机缺少 借用网图)
成功!