~~~写在前面的话~~~
我之前打算做一个APP,然后把电话号码生成二维码 或者条形码, 用手机扫描,这样,就不用担心会输入错误电话号码了。
在下面是实现的扫描二维码的功能中,扫描完成,将会把扫描到的号码 拨打出去。~~~
关于应用之间的切换,参考链接:
http://blog.sina.com.cn/s/blog_7ea0400d0102uy01.html
~~CSDN不知道怎么了,贴代码的地方不能有横向的滚动条了,不过,可以用下面的方法查看到具体代码呢~~
------------我是分割线--------------
基于AVFoundation实现的。
1、效果图
生成界面
扫描界面:
2、环境
ios9.3.2
Xcode7.3(swift 3)
~~新建项目~~
A、新建文件:QRCode View.swift,该文件主要用来生成二维码
import UIKit /// 生成二维码 class QRCodeView: UIView { /** - logo - parameter surperImage: 二维码 - parameter subImage: logo - parameter postRext: logo位置 - returns: 返回加上logo的图片 */ private func imageViewAddImage(surperImage: UIImage,subImage: UIImage,postRect:CGRect) -> UIImage { //// 创建图像 UIGraphicsBeginImageContext(surperImage.size); //// 设置坐标 surperImage.drawInRect(CGRect(x:0,y:0,width: surperImage.size.width,height: surperImage.size.height)); surperImage.drawInRect(postRect); //// 返回一个图像基于当前位图图形 let newImage = UIGraphicsGetImageFromCurrentImageContext(); //// 移除当前位图图形 UIGraphicsEndImageContext(); return newImage; } /** 调整大小 - parameter ciImage: 待改变的image - parameter width: 设置比例系数 - returns: 设置比例后的图片 */ private func SetSize(ciImage: CIImage,_width:CGFloat) -> UIImage { let extent = CGRectIntegral(ciImage.extent); let scale = min(_width / CGRectGetWidth(extent),_width / CGRectGetHeight(extent)); let width = CGRectGetWidth(extent) * scale; let height = CGRectGetHeight(extent) * scale; let cs = CGColorSpaceCreateDeviceGray(); let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.None.rawValue); let bitmapRef = CGBitmapContextCreate(nil,Int(width),Int(height),8,cs,bitmapInfo.rawValue); let context = CIContext(options: [kCIContextUseSoftwareRenderer:(true)]); let bitmapImage = context.createCGImage(ciImage,fromRect: extent); CGContextSetInterpolationQuality(bitmapRef,CGInterpolationQuality.None) CGContextScaleCTM(bitmapRef,scale,scale) CGContextDrawImage(bitmapRef,extent,bitmapImage); let scaledImage = CGBitmapContextCreateImage(bitmapRef); return UIImage(CGImage: scaledImage!); } /** 截取logo边角 - parameter cornerRadius: 截取度 - parameter image: 需要截取边角的图片 - returns: 截取边角后的图片 */ private func ImageAfterCutOutCorner(cornerRadius:CGFloat,image:UIImage) -> UIImage { let frame = CGRectMake(0,image.size.width,image.size.height); UIGraphicsBeginImageContextWithOptions(image.size,false,1.0); UIBezierPath.init(roundedRect:frame,cornerRadius: cornerRadius).addClip(); image.drawInRect(frame); let im = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return im; } /** 生成二维码 - parameter urlString: 电话号码 - parameter surperView: image View - parameter logo: logo的位置 - parameter logoSize: logo的大小 - parameter cornerRadius: 边角裁剪度 - returns: 二维码 */ class func GenerateQRCode(urlString:String,surperView:UIView,logo:UIImage,logoSize:CGSize,cornerRadius: CGFloat) -> QRCodeView { let qrCodeView = QRCodeView(); qrCodeView.frame = CGRect(x: 0,y: 0,width: surperView.frame.size.width,height: surperView.frame.size.height); //// 该参数代表二维码不可改变 let filter = CIFilter.init(name: "CIQRCodeGenerator"); filter?.setDefaults(); filter?.setValue(urlString.dataUsingEncoding(NSUTF8StringEncoding),forKey: "inputMessage"); //inputMessage 固定写法,代表输入信息 的意思 let ciImage = filter?.outputImage; let QRImage = qrCodeView.SetSize(ciImage!,_width: surperView.frame.width); var cornerRadius_1 = cornerRadius; if (!logo.isEqual(nil)) { if (cornerRadius_1 < 0) { cornerRadius_1 = 0; } } qrCodeView.layer.contents = QRImage.CGImage; surperView.addSubview(qrCodeView); return qrCodeView; } }
C、在ViewController.swift 文件中调用。
D、在main.storyboard中添加控件:
E、在viewcontroller.swift 做关联:
F、同理,在 viewcontroller.swift 关联按钮的事件
G、关联完成,接着就在viewcontroller.swift中调用创建二维码了
生成二维码,当然是写在这个按钮下啦。 在 F 的函数中写上如下代码:
/** 生成按钮 - parameter sender: nothing */ @IBAction func BtnGenerateQRCode(sender: UIButton) { label.text = ""; if (textField.text == "") { label.font = UIFont.systemFontOfSize(20); label.text = "电话号码不能为空"; return; } textField.resignFirstResponder();/// 取消焦点 // 生成二维码 QRCodeView.GenerateQRCode(textField.text!,surperView: imageView,logo: UIImage(named: "logo")!,logoSize: CGSizeMake(100,100),cornerRadius: CGFloat(1000)); }同时,在ViewDidLoad方法中写上代码,设置控件属性
/** 窗口加载 */ override func viewDidLoad() { super.viewDidLoad(); label.adjustsFontSizeToFitWidth = true;// 设置自适应 label.text = ""; /// 清空 // Do any additional setup after loading the view,typically from a nib. }
OK,二维码生成完成~~~
下面是 viewcontroller.swift 的详细源码:
// // ViewController.swift // GenerateQRCode // // Created by driver on 16/9/7. // Copyright © 2016年 driver. All rights reserved. // import UIKit class ViewController: UIViewController { /// 提示label @IBOutlet weak var label: UILabel! /// 二维码显示框 @IBOutlet weak var imageView: UIImageView! /// 电话号码输入框 @IBOutlet weak var textField: UITextField! /** 窗口加载 */ override func viewDidLoad() { super.viewDidLoad(); label.adjustsFontSizeToFitWidth = true;// 设置自适应 label.text = ""; /// 清空 // Do any additional setup after loading the view,typically from a nib. } /** 生成按钮 - parameter sender: nothing */ @IBAction func BtnGenerateQRCode(sender: UIButton) { label.text = ""; if (textField.text == "") { label.font = UIFont.systemFontOfSize(20); label.text = "电话号码不能为空"; return; } textField.resignFirstResponder();/// 取消焦点 // 生成二维码 QRCodeView.GenerateQRCode(textField.text!,cornerRadius: CGFloat(1000)); } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } }
///-----我是分割线--------------------
4、扫描二维码
~~~~ 新建项目~~~
A、扫描,就是在main.storyboard 中添加一个控件:按钮, 然后关联其touch事件。
B、在 Viewcontroller.swift 中,导入的库:
import UIKit import AVFoundationC、
ViewController类继承的有:
UIViewController,AVCaptureMetadataOutputObjectsDelegate代码:
class ViewController: UIViewController,AVCaptureMetadataOutputObjectsDelegateD、viewcontroller类 定义的属性有:
////定义属性 var session: AVCaptureSession?; var layer: AVCaptureVideoPreviewLayer?;
E、viewDidLoad方法中添加代码:
super.viewDidLoad(); ///self.view.backgroundColor = UIColor.lightGrayColor(); self.modalPresentationStyle = .Custom;F、在自己关联的按钮事件函数,源码如下:
////扫描 @IBAction func scanQRcode(sender: AnyObject) { self.session = AVCaptureSession(); //// let device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo); do { let input = try AVCaptureDeviceInput(device: device); if (self.session!.canAddInput(input)) { self.session!.addInput(input); } ////输出 let output = AVCaptureMetadataOutput(); output.setMetadataObjectsDelegate(self,queue: dispatch_get_main_queue()); if (self.session!.canAddOutput(output)) { self.session!.addOutput(output) output.MetadataObjectTypes = [AVMetadataObjectTypeQRCode]; } ////添加图层 self.layer = AVCaptureVideoPreviewLayer(session:self.session!); self.layer!.frame = self.view.frame; self.view.layer.addSublayer(self.layer!); //// 开始扫描 self.session?.startRunning(); } catch let error as NSError { print(error); } }
F、实现 AVCaptureMetadataOutputObjectsDelegate 委托中的方法:
////委托 @objc func captureOutput(captureOutput: AVCaptureOutput!,didOutputMetadataObjects MetadataObjects: [AnyObject]!,fromConnection connection: AVCaptureConnection!) { let stringValue:String?; if (MetadataObjects.count > 0) { let MetadataObject = MetadataObjects[0] as! AVMetadataMachineReadableCodeObject; //// stringValue = MetadataObject.stringValue; if (nil != stringValue) ////这里捕捉到二维码 { self.session!.stopRunning(); //// 移除图层 self.layer!.removeFromSuperlayer(); ////启动拨号~~ UIApplication.sharedApplication().openURL(NSURL(string: "tel://\(stringValue)")!); // let alertView = UIAlertController(title: "二维码",message: stringValue,preferredStyle: .Alert); // let action = UIAlertAction(title: "OK",style: UIAlertActionStyle.Default,handler: nil); // alertView.addAction(action); ////显示提示框 // self.presentViewController(alertView,animated: true,completion:nil); } else { let alertView = UIAlertController(title: "二维码",message: "没有扫描到二维码",preferredStyle: .Alert); let action = UIAlertAction(title: "OK",handler: nil); alertView.addAction(action); ////显示提示框 self.presentViewController(alertView,completion:nil); } } }
import UIKit import AVFoundation class ViewController: UIViewController,AVCaptureMetadataOutputObjectsDelegate { ////定义属性 var session: AVCaptureSession?; var layer: AVCaptureVideoPreviewLayer?; ////方法 override func viewDidLoad() { super.viewDidLoad(); ///self.view.backgroundColor = UIColor.lightGrayColor(); self.modalPresentationStyle = .Custom; } ////扫描 @IBAction func scanQRcode(sender: AnyObject) { self.session = AVCaptureSession(); //// let device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo); do { let input = try AVCaptureDeviceInput(device: device); if (self.session!.canAddInput(input)) { self.session!.addInput(input); } ////输出 let output = AVCaptureMetadataOutput(); output.setMetadataObjectsDelegate(self,queue: dispatch_get_main_queue()); if (self.session!.canAddOutput(output)) { self.session!.addOutput(output) output.MetadataObjectTypes = [AVMetadataObjectTypeQRCode]; } ////添加图层 self.layer = AVCaptureVideoPreviewLayer(session:self.session!); self.layer!.frame = self.view.frame; self.view.layer.addSublayer(self.layer!); //// 开始扫描 self.session?.startRunning(); } catch let error as NSError { print(error); } } ////委托 @objc func captureOutput(captureOutput: AVCaptureOutput!,completion:nil); } } } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } }