ViewController
import UIKit
import AVFoundation
class ViewController: UIViewController {
let captureSession = AVCaptureSession()
var readerRect = CGRect.zero
let line = UIImageView()
var uping = true
var timer: NSTimer?
let kWidth = UIScreen.mainScreen().bounds.size.width
let kHeight = UIScreen.mainScreen().bounds.size.height
override func viewDidLoad() {
super.viewDidLoad()
title = "二维码扫描"
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "选取图片", style: .Done, target: self, action: #selector(presentImgPicker))
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "生成二维码", style: .Done, target: self, action: #selector(pushToGenerator))
let status = AVCaptureDevice.authorizationStatusForMediaType(AVMediaTypeVideo)
switch status {
case .NotDetermined://用户未决定
AVCaptureDevice.requestAccessForMediaType(AVMediaTypeVideo, completionHandler: {
return $0 == true ? self.initialization() : self.showAlert()
})
case .Authorized://已允许权限
initialization()
case .Restricted: break//权限受限
case .Denied://拒绝权限
showAlert()
}
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
if !captureSession.running {
captureSession.startRunning()
}
fireTimer()
}
override func viewDidDisappear(animated: Bool) {
super.viewDidDisappear(animated)
captureSession.stopRunning()
if (timer != nil) {
timer!.invalidate()
timer = nil
}
}
func presentImgPicker() {
let imgPicker = UIImagePickerController()
imgPicker.sourceType = .PhotoLibrary
imgPicker.delegate = self
presentViewController(imgPicker, animated: true, completion: nil)
}
func pushToGenerator() {
let genVC = GeneratorVC(nibName: "GeneratorVC", bundle: nil)
navigationController?.pushViewController(genVC, animated: true)
}
func initialization() {
initScanRect()
setupSession()
setupScanLine()
makeShawdowView()
fireTimer()
}
func showAlert() {
let alert = UIAlertController(title: "提示", message: "请前往\"设置->隐私->相机->二维码\"打开相机权限", preferredStyle: .Alert)
let action = UIAlertAction(title: "确定", style: .Cancel, handler: nil)
alert.addAction(action)
presentViewController(alert, animated: true, completion: nil)
}
func initScanRect() {
let scanWidth = kWidth * 2 / 3
readerRect = CGRect(x: (kWidth - scanWidth) / 2, y: (kHeight - scanWidth) / 2 * 0.8, width: scanWidth, height: scanWidth)
}
func setupSession() {
let captureDevice = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
let input: AVCaptureDeviceInput?
do {
input = try AVCaptureDeviceInput(device: captureDevice)
} catch _ {
fatalError("Could not create capture device input.")
}
captureSession.addInput(input)
let output = AVCaptureMetadataOutput()
captureSession.addOutput(output)
output.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue())
output.metadataObjectTypes = [AVMetadataObjectTypeQRCode,
AVMetadataObjectTypeCode93Code,
AVMetadataObjectTypeCode39Code,
AVMetadataObjectTypeCode128Code]
let layer = AVCaptureVideoPreviewLayer.init(session: captureSession)
layer.videoGravity = AVLayerVideoGravityResizeAspectFill
layer.frame = view.bounds
view.layer .insertSublayer(layer, atIndex: 0)
let x = readerRect.origin.x / kWidth
let y = readerRect.origin.y / kHeight
let width = readerRect.size.width / kWidth
let height = readerRect.size.height / kHeight
output.rectOfInterest = CGRect(x: x, y: y, width: width, height: height)
captureSession.startRunning()
}
func setupScanLine() {
let imgWidth: CGFloat = 20.0
let imgX: CGFloat = readerRect.origin.x
let imgY: CGFloat = readerRect.origin.y
let width = CGFloat(readerRect.size.width)
let height = CGFloat(readerRect.size.height)
let cornerTL = CGRect(x: imgX, y: imgY, width: imgWidth, height: imgWidth)
let cornerTR = CGRect(x: imgX + width - imgWidth, y: imgY, width: imgWidth, height: imgWidth)
let cornerBL = CGRect(x: imgX, y: imgY+height-imgWidth, width: imgWidth, height: imgWidth)
let cornerBR = CGRect(x: imgX + width - imgWidth, y: imgY+height-imgWidth, width: imgWidth, height: imgWidth)
let frames = [cornerTL, cornerTR, cornerBL, cornerBR]
for (index, frame) in frames.enumerate() {
let imgView = UIImageView(frame: frame)
imgView.image = UIImage(named: "ScanQR\(index + 1)")
view.addSubview(imgView)
}
let lineRect = CGRect(x: imgX, y: imgY, width: width, height: width / 640 * 24)
line.frame = lineRect
line.image = UIImage(named: "ScanLine")
view.addSubview(line)
let label = UILabel(frame: CGRect(x: 0, y: imgY + height + 20, width: kWidth, height: 20))
label.textAlignment = .Center
label.font = UIFont.systemFontOfSize(12)
label.textColor = UIColor.whiteColor()
label.text = "请将二维码放入框内,即可自动扫描!"
view.addSubview(label)
}
func makeShawdowView() {
UIGraphicsBeginImageContext(view.bounds.size)
let context = UIGraphicsGetCurrentContext()
UIColor(white: 0, alpha: 0.55).setFill()
CGContextFillRect(context, view.bounds)
UIColor.whiteColor().setStroke()
CGContextStrokeRectWithWidth(context, readerRect, 1)
CGContextClearRect(context, readerRect)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
let shadowBgview = UIImageView(frame: view.bounds)
shadowBgview.image = image
view.addSubview(shadowBgview)
}
func fireTimer() {
timer = NSTimer.scheduledTimerWithTimeInterval(0.02, target: self, selector: #selector(beginAnimation), userInfo: nil, repeats: true)
}
func beginAnimation() {
var frame = line.frame
if uping {
if CGRectGetMinY(frame) > CGRectGetMinY(readerRect) {
frame.origin.y -= 2
line.frame = frame
return
}
uping = false
} else {
if CGRectGetMaxY(frame) < CGRectGetMaxY(readerRect) {
frame.origin.y += 2
line.frame = frame
return
}
uping = true
}
}
}
extension ViewController: AVCaptureMetadataOutputObjectsDelegate {
func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!) {
if metadataObjects.count > 0 {
captureSession.stopRunning()
timer!.invalidate()
timer = nil
let obj = metadataObjects.first as! AVMetadataMachineReadableCodeObject
let resultVC = ResultViewController()
resultVC.result = obj.stringValue
navigationController?.pushViewController(resultVC, animated: true)
}
}
}
extension ViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
let detector = CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: [CIDetectorAccuracy:CIDetectorAccuracyHigh])
let img = info[UIImagePickerControllerOriginalImage] as! UIImage
let image = CIImage.init(image: img)
let features = detector.featuresInImage(image!)
picker.dismissViewControllerAnimated(true) {
if features.count > 0 {
let resultVC = ResultViewController()
let feature: CIQRCodeFeature = features[0] as! CIQRCodeFeature
resultVC.result = feature.messageString
self.navigationController?.pushViewController(resultVC, animated: true)
}
}
for feature in features {
let fea = feature as! CIQRCodeFeature
print(fea.messageString)
}
}
func imagePickerControllerDidCancel(picker: UIImagePickerController) {
picker.dismissViewControllerAnimated(true, completion: nil)
}
}
GeneratorVC
import UIKit
import AVFoundation
class GeneratorVC: UIViewController, UIGestureRecognizerDelegate {
@IBOutlet weak var inputField: UITextField!
@IBOutlet weak var imageView: UIImageView!
@IBOutlet weak var infoLabel: UILabel!
var selImage: UIImage?
var showImage: UIImage?
override func viewDidLoad() {
super.viewDidLoad()
imageView.hidden = true
imageView.userInteractionEnabled = true
infoLabel.hidden = true
let longGesture = UILongPressGestureRecognizer(target: self, action: #selector(saveQRCode))
longGesture.delegate = self;
imageView.addGestureRecognizer(longGesture)
let status = AVCaptureDevice.authorizationStatusForMediaType(AVMediaTypeVideo)
switch status {
case .NotDetermined:
AVCaptureDevice.requestAccessForMediaType(AVMediaTypeVideo, completionHandler: {
if !$0 {
self.showAlert()
}
})
case .Authorized: break
case .Restricted: break
case .Denied:
showAlert()
}
}
func saveQRCode() {
let alert = UIAlertController(title: "", message: "是否保存到本地相册", preferredStyle: .Alert)
let action1 = UIAlertAction(title: "取消", style: .Cancel, handler: nil)
let action2 = UIAlertAction(title: "确定", style: .Default) { (action) in
UIImageWriteToSavedPhotosAlbum(self.showImage!, nil, nil, nil)
}
alert.addAction(action1)
alert.addAction(action2)
presentViewController(alert, animated: true, completion: nil)
}
func showAlert() {
let alert = UIAlertController(title: "提示", message: "请前往\"设置->隐私->相机->二维码\"打开相机权限", preferredStyle: .Alert)
let action = UIAlertAction(title: "确定", style: .Cancel, handler: nil)
alert.addAction(action)
presentViewController(alert, animated: true, completion: nil)
}
func generatorCode() {
view.endEditing(true)
var info = inputField.text
if (info == "") {
info = "http://www.jianshu.com/users/46342fd00794/latest_articles"
}
let data = info?.dataUsingEncoding(NSUTF8StringEncoding)
let filter = CIFilter(name: "CIQRCodeGenerator")
filter?.setValue(data, forKey: "inputMessage")
filter?.setValue("H", forKey: "inputCorrectionLevel")
let outputImage = filter?.outputImage
let transform = CGAffineTransformMakeScale(5, 5)
let transformImage = outputImage?.imageByApplyingTransform(transform)
let context = CIContext(options: nil)
let imageRef = context.createCGImage(transformImage!, fromRect: (transformImage?.extent)!)
let qrImage = UIImage(CGImage: imageRef)
let size = qrImage.size
UIGraphicsBeginImageContext(size)
qrImage.drawInRect(CGRect(x: 0, y: 0, width: size.width, height: size.height))
let width = size.width * 0.3
if selImage != nil {
selImage?.drawInRect(CGRect(x: (size.width - width)/2, y: (size.width - width)/2, width: width, height: width))
}
showImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
imageView.image = showImage
imageView.hidden = false
infoLabel.hidden = false
}
@IBAction func pickImage(sender: AnyObject) {
let imgPicker = UIImagePickerController()
imgPicker.sourceType = .PhotoLibrary
imgPicker.delegate = self
presentViewController(imgPicker, animated: true, completion: nil)
}
}
extension GeneratorVC: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
selImage = info[UIImagePickerControllerOriginalImage] as? UIImage
generatorCode()
picker.dismissViewControllerAnimated(true, completion: nil)
}
func imagePickerControllerDidCancel(picker: UIImagePickerController) {
picker.dismissViewControllerAnimated(true, completion: nil)
}
}
ResultViewController
import UIKit
class ResultViewController: UIViewController {
internal var result = ""
let kWidth = UIScreen.mainScreen().bounds.size.width
let kHeight = UIScreen.mainScreen().bounds.size.height
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.whiteColor()
if !result.isEmpty {
let httpAddresses = getUrlAddress(result)
if httpAddresses.count > 0 {
let http = httpAddresses.first!
print(http)
let webView = UIWebView(frame: CGRect(x: 0, y: 0, width: kWidth, height: kHeight))
view.addSubview(webView)
let request = NSURLRequest(URL: NSURL(string: http)!)
webView.loadRequest(request)
} else {
for index in 0...1 {
let label = UILabel(frame: CGRect(x: 0, y: 164 + 80 * index, width: Int(kWidth), height: 50))
label.textColor = UIColor.blueColor()
label.font = UIFont.systemFontOfSize(25)
label.adjustsFontSizeToFitWidth = true
if index == 0 {
label.text = " 您的二维码信息如下:"
} else {
label.text = result
label.textAlignment = .Center
}
view.addSubview(label)
}
}
}
}
func getUrlAddress(text: String) -> [String] {
let pattern = "http?://([-\\w\\.]+)+(:\\d+)?(/([\\w/_\\.]*(\\?\\S+)?)?)?"
var matches = [String]()
do {
let regex = try NSRegularExpression(pattern: pattern, options: NSRegularExpressionOptions(rawValue: 0))
let nsstr = text as NSString
let all = NSRange(location: 0, length: nsstr.length)
regex.enumerateMatchesInString(text, options: NSMatchingOptions.init(rawValue: 0), range: all, usingBlock: { (result, flags, _) in
matches.append(nsstr.substringWithRange(result!.range))
})
} catch {
return [String]()
}
return matches
}
}