How do I use Swift to develop a simple barcode detector?

Source: Internet
Author: User

"Editor's note" The writer is Matthew Maher, who mainly hands-on how to build a simple barcode detector with Swift. The article is compiled and collated by OneAPM engineers.

The barcode scanner is a simple and practical tool for supermarket cashiers to scan the goods, enter luggage or check passengers in the airport, or perform inventory management activities in large retailers. In fact, the barcode scanner also helps consumers realize the use of intelligent shopping, goods classification and so on. This time, we will develop a scanner for the iphone.

We are fortunate that Apple has made it easy to implement the barcode scanning process. We'll dive into the AV Foundation framework to develop a simple app that scans the CD barcode, then get the key information for the album, and finally print it out in the app's interface. It's also important to read the barcode, and we'll take further action based on the barcode we read.

Needless to say, the device that can sweep the code must have a camera. From here, let's get started with an iOS device with a webcam!

About Cdbarcodes

The app we developed today is called cdbarcodes--, which is the barcode scanning object is CD. When our device detects a barcode, it picks up the code and sends it to the Discogs database for its album name, artist name, and year of release. Discogs's music database is very powerful, so we are likely to find some useful information.

Download the initial project for Cdbarcodes.

In addition to a good database, Discogs also has a practical API to help with queries. We're only dealing with a small subset of the features that Discogs provides to developers, but that's enough to get our app running.

Discogs

Go to the Discogs website. First we must register a discogs account and log in. After that, pull down to the bottom of the page. Click API in the leftmost column of the footer.

Click Search in the database area on the left side of the Discogs API interface.

This is the endpoint of our query. We will get the album information from both the "title" and "Year" parameters.

Now, we'll record this URL in cdbarcodes for subsequent queries. Constants.swiftadd DISCOGS_AUTH_URL and assign values https://api.discogs.com/database/search?q= as constants in.

let DISCOGS_KEY = "your-discogs-key"

Now we are able to invoke the URL through the entire app DISCOGS_AUTH_URL .

Go back to Discogs's API page, choose to create a new app, and get some authentication information. In the navigation bar at the top of the page, find the "Create an App" and click the button.

Enter "Cdbarcodes Your name" in the app Name field, or any other appropriate name. Description You can use the following text:

"This is an iOS app that is designed to display album information after reading the barcode of a CD. ”

Then, click on "Create Application" (that is, creating an app) button.

On the end page, you'll see authentication information that allows us to use barcodes.

Copy "Consumer key" (user key) to Constants.swift the DISCOGS_KEY inside.

With this URL, we can easily use these parameters throughout the Cdbarcodes application.

CocoaPods

We use the powerful dependency manager (dependency manager) Cocoapods to interact with the Discogs API. For cocoapods installation and other information, you can refer to the Cocoapods website.

Via Cocoapods, on the network side we will use Alamofire and Swiftyjson to process the JSON returned by Discogs.

Now start in cdbarcodes Combat!

Install Cocoapods, open the terminal interface, tune to Cdbarcodes, and use the following code to initialize the Coccoapods in the Xcode project:

cd <your-xcode-project-directory>pod init

Open Podfile file in Xcode:

open -a Xcode Podfile

Enter or copy and paste the following code into the Podfile file:

source ‘https://github.com/CocoaPods/Specs.git‘platform :ios, ‘8.0‘use_frameworks!pod ‘Alamofire‘, ‘~> 3.0‘target ‘CDBarcodes’ dopod ‘SwiftyJSON‘, :git => ‘https://github.com/SwiftyJSON/SwiftyJSON.git‘end

Finally, run the following code to download Alamofire and Swiftyjson:

pod install

Now go back to xcode!. Note that when you develop the app, you keep the Cdbarcodes.xcworkspace open (workspace).

Barcode Reader

Apple's AV Foundation framework provides the tools we need to develop this barcode reader app. Here are a few things to be involved in the process:

    • The avcapturesession will process the input and output data from the camera.

    • Avcapturedevice refers to physical devices and other properties. Avcapturesession accepts input information from Avcapturedevice.

    • Avcapturedeviceinput gets the input data from the input device.

    • Avcapturemetadataoutput sends a metadata object to the proxy object (delegate objects) for processing.

BarcodeReaderViewController.swiftinside, our first step is to import avfoundation.

import UIKitimport AVFoundation

Note to follow AVCaptureMetadataOutputObjectsDelegate .

In viewDidLoad() , will run our barcode reading engine.

First, create a new AVCaptureSession object and set it AVCaptureDevice . We then create a new input object and add it to the AVCaptureSession .

class BarcodeReaderViewController: UIViewController, AVCaptureMetadataOutputObjectsDelegate {var session: AVCaptureSession!var previewLayer: AVCaptureVideoPreviewLayer!override func viewDidLoad() {    super.viewDidLoad()    // Create a session object. 新建一个模块对象    session = AVCaptureSession()    // Set the captureDevice. 设置captureDevice    let videoCaptureDevice = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)    // Create input object. 新建输入设备    let videoInput: AVCaptureDeviceInput?    do {        videoInput = try AVCaptureDeviceInput(device: videoCaptureDevice)    } catch {        return    }    // Add input to the session. 将输入添加至模块中    if (session.canAddInput(videoInput)) {        session.addInput(videoInput)    } else {        scanningNotPossible()    }

If the device happens to have no camera, the scanning process will not be possible. Therefore, we need an error function. Here, we inform the user to look for a camera-equipped iOS device for the next CD barcode reading.

func scanningNotPossible() {    // Let the user know that scanning isn‘t possible with the current device. 告知用户扫描现有设备无法扫描    let alert = UIAlertController(title: "Can‘t Scan.", message: "Let‘s try a device equipped with a camera.", preferredStyle: .Alert)    alert.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))    presentViewController(alert, animated: true, completion: nil)    session = nil}

Back viewDidLoad() , after adding the input to the (session) module, we then created AVCaptureMetadataOutput and added it to the module. We send the captured data to the proxy object in the form of a serial sequence.

The next step is to identify the type of barcode we should scan. Here we are facing the EAN-13 type of barcode. Interestingly, not all barcodes are of this type; some will be upc-a format. This can cause errors to occur.

The Apple will automatically convert the UPC-A format bar code to the EAN-13 format before adding a 0. Barcodes in the UPC-A format have only 12 digits, whereas in the EAN-13 format barcodes are 13 bits. One of the benefits of this automatic conversion process is that we can query metadataObjectTypes AVMetadataObjectTypeEAN13Code , so we can read the barcode in both formats. Note that this conversion directly alters the barcode to mislead the Discogs database. But don't worry, we'll solve the problem right away.

In any case, we will direct the user to the function when there is a problem with the user device camera scanningNotPossible() .

// Create output object. 新建输出对象let metadataOutput = AVCaptureMetadataOutput()// Add output to the session. 将输出添加至模块if (session.canAddOutput(metadataOutput)) {    session.addOutput(metadataOutput)    // Send captured data to the delegate object via a serial queue. 通过串行序列将捕捉到的数据发送至代理对象。    metadataOutput.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue())    // Set barcode type for which to scan: EAN-13. 设置需要扫描的条形码类型:EAN-13    metadataOutput.metadataObjectTypes = [AVMetadataObjectTypeEAN13Code]} else {    scanningNotPossible()}

Now we're done with this cool feature, pull it out and sneak out! We will use the AVCaptureVideoPreviewLayer entire screen to show the video.

Finally, we start capturing the module.

// Add previewLayer and have it show the video data. 添加previewLayer并展示视频数据    previewLayer = AVCaptureVideoPreviewLayer(session: session);    previewLayer.frame = view.layer.bounds;    previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;    view.layer.addSublayer(previewLayer);    // Begin the capture session. 开启捕捉模块    session.startRunning()

captureOutput:didOutputMetadataObjects:fromConnectionin, we celebrate, as our barcode reader found something!

Through captureOutput:didOutputMetadataObjects:fromConnection , our barcode reader has finally read some data.

First, we need to use the first object to get the metadataObjects array and convert it to a machine-readable code. We then send the readableCode string to the barcodeDetected() .

Before entering the barcodeDetected() function, we will stop capturing the module and give the user a vibration feedback. If we forget to stop the capture module, then the vibration will not be stopped! That's why this is a good case.

func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!) {    // Get the first object from the metadataObjects array. 获得metadataObjects数组的第一个对象    if let barcodeData = metadataObjects.first {        // Turn it into machine readable code 转换为可机读代码        let barcodeReadable = barcodeData as? AVMetadataMachineReadableCodeObject;        if let readableCode = barcodeReadable {            // Send the barcode as a string to barcodeDetected() 发送条形码数据            barcodeDetected(readableCode.stringValue);        }        // Vibrate the device to give the user some feedback. 震动反馈        AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate))        // Avoid a very buzzy device. 结束捕捉模块        session.stopRunning()    }}

barcodeDetected()we have a lot of things to do inside the function. The first task is to prompt the user after the vibration feedback that we have found the barcode. Then we start working with the data we found!

Spaces in the bar code must be removed. After that we need to make sure that the barcode format is EAN-13 or upc-a. If it is EAN-13 we can use it directly. If the object is a upc-a code, it has been converted to the EAN-13 format, and we need to convert it to the original format.

As we have discussed earlier, the Apple device adds a 0 to the UPC-A format before it is converted to the EAN-13 format, so we first determine that the code starts with 0. If it is, we need to remove it. Without this step, the Discogs database will not recognize this number and we will not be able to get the data we want.

After obtaining the cleaned barcode string, we send it to DataService.searchAPI() and eject it BarcodeReaderViewController.swift .

Func barcodedetected (code:string) {//Let the user know we ' ve found something. Inform the user of the scan result. Alert = Uialertcontrol Ler (title: "Found a barcode!", Message:code, PreferredStyle:UIAlertControllerStyle.Alert) alert.addaction (uialertact        Ion (title: "Search", Style:UIAlertActionStyle.Destructive, Handler: {action in//remove the spaces. Remove spaces  Let Trimmedcode = Code.stringbytrimmingcharactersinset (Nscharacterset.whitespacecharacterset ())//EAN or UPC?        Determine the format//Check for added ' 0 ' at beginning of code. Let trimmedcodestring = "\ (trimmedcode)" Var trimmedcodenozero:string if Trimmedcodestring.hasprefix ("0") & amp;& trimmedCodeString.characters.count > 1 {trimmedcodenozero = String (trimmedcodestring.characters.d Ropfirst ())//Send the doctored UPC to DATASERVICE.SEARCHAPI () sends UPC to API Dataservice.searchapi (tri Mmedcodenozero)} else {//Send the doctored EAN to Dataservice.seaRchapi () Dataservice.searchapi (trimmedcodestring)} Self.navigationcontroller?. Popviewcontrolleranimated (True)}) Self.presentviewcontroller (Alert, Animated:true, Completion:nil)}

Before leaving BarcodeReaderViewController.swift , in the viewDidLoad() following, we add viewWillAppear() and viewWillDisappear() function. The viewWillAppear() capture module will be turned on, and viewWillDisappear() the module will be terminated.

override func viewWillAppear(animated: Bool) {    super.viewWillAppear(animated)    if (session?.running == false) {        session.startRunning()    }}override func viewWillDisappear(animated: Bool) {    super.viewWillDisappear(animated)    if (session?.running == true) {        session.stopRunning()    }}
Data Services

In DataService.swift , we will first import Alamofire and Swiftyjson.

Next, we declare some variables to store the raw data returned from Discogs. Based on BIONIK6 's recommendations, we cleverly use private(set) functions to avoid the blocking problems that users may cause.

Then, establish a Alamofire get request. Here the JSON will be parsed to get the title of the album and year (release years). The original title and year strings are assigned and will be ALBUM_FROM_DISCOGS YEAR_FROM_DISCOGS used later to initialize our albums.

Now that we have data from Discogs, we can officially open the show, and we'll notify Albumdetailsviewcontroller.swift The information captured by the module.

Import Foundationimport Alamofireimport swiftyjsonclass DataService {static Let DataService = DataService () private (set) var album_from_discogs = "" Private (set) var year_from_discogs = "" Static func Searchapi (codenumber:string) {//the UR L We'll use the Get Out album data from Discogs using URL to get Discogsurl = "\ (discogs_auth_url) \ (codenumber) &?barc Ode&key=\ (Discogs_key) &secret=\ (Discogs_secret) "Alamofire.request (.            GET, Discogsurl). Responsejson {response in var JSON = JSON (response.result.value!)            Let Albumartisttitle = "\ (json[" Results "][0][" title "]) ' let albumyear = ' \ (json[" Results "][0][" year "])"            Self.dataService.ALBUM_FROM_DISCOGS = Albumartisttitle Self.dataService.YEAR_FROM_DISCOGS = albumyear Post a notification to let Albumdetailsviewcontroller know we have some data. Notice Albumdetailsviewcontroller nsnotificationcenter.defaultcenter (). Postnotificationname ("AlbumNotification ", Object:nil)}}} 
Album Module

In the album Module Album.swift , we process the album data to meet our requirements. This module will fetch the original artistAlbum and albumYear string and then make them user-friendly. AlbumDetailsViewController.swiftafter we show the processing album and year information.

import Foundationclass Album {        private(set) var album: String!private(set) var year: String!init(artistAlbum: String, albumYear: String) {    // Add a little extra text to the album information 添加额外专辑信息    self.album = "Album: \n\(artistAlbum)"    self.year = "Released in: \(albumYear)"}}
Album Show Time!

In the viewDidLoad() module, set the label (label) that points to the barcode reader. Then we need to NSNotification add the Observer (Observer) so that we have shown the hint to be able to cluster. In deinit , we will remove the Observer (Observer).

deinit {    NSNotificationCenter.defaultCenter().removeObserver(self)}override func viewDidLoad() {    super.viewDidLoad()    artistAlbumLabel.text = "Let‘s scan an album!"    yearLabel.text = ""    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(setLabels(_:)), name: "AlbumNotification", object: nil)}

When the notification appears, the setLabels() function is called. Here we will use DataService.swift the original data from the initialization Album . The label will show the processed string.

func setLabels(notification: NSNotification){    // Use the data from DataService.swift to initialize the Album.    let albumInfo = Album(artistAlbum: DataService.dataService.ALBUM_FROM_DISCOGS, albumYear: DataService.dataService.YEAR_FROM_DISCOGS)    artistAlbumLabel.text = "\(albumInfo.album)"    yearLabel.text = "\(albumInfo.year)"}
Test Cdbarcodes

After the application is set up, sweep the barcode of the CD and we can determine the name of the album, the Artist and the year of release information, which is very interesting! To better test the cdbarcodes, we can find some CDs or vinyl records at random. This makes it more organic to encounter cases of EAN-13 and upc-a in two barcode formats. Now we can handle both!

To make the application run smoothly into the Barcodereaderviewcontroller module, be careful to avoid flash to ensure that the camera can capture the barcode information.

Here is the download link for the full code.

Conclusion

This barcode reader is useful, whether it's a businessman, a savvy consumer or a general person. Therefore, it is very good for developers to use this case to practice practiced hand.

But we also see that the interesting thing is just the sweep code section. After obtaining the data, we encountered a small problem, such as EAN-13 and upc-a format problems. We have found a solution to the problem to meet the needs.

Next, we can explore some of the other metadataObjectTypes and some new APIs. Opportunities are endless and experience is priceless.

This article is compiled and collated by OneAPM engineers. OneAPM Mobile Insight provides a real user experience as a metric for Crash analysis, monitoring network requests and network errors, and improving user retention. Visit the official website of OneAPM for more application performance optimization experiences and to read more technical articles, visit the OneAPM Official technology blog.

This article was transferred from OneAPM official blog

Original link: http://www.appcoda.com/simple-barcode-reader-app-swift/

How do I use Swift to develop a simple barcode detector?

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.