ฉันจะสแกนบาร์โค้ดบน iOS ได้อย่างไร


189

ฉันจะสแกนบาร์โค้ดบน iPhone และ / หรือ iPad ได้อย่างไร


7
น่าเศร้าที่ปัจจุบันกล้อง iPhone นั้นแย่มากสำหรับการอ่านบาร์โค้ดเนื่องจากเลนส์ได้รับการโฟกัสไปที่∞ โชคดีที่สุด!
Alastair Stuart

1
เพิ่งแก้ปัญหานี้ไปแล้วจะเขียนข้อสังเกตของฉัน ฉันทดสอบตัวเลือกน้อย RSBarcodes_Swift - ง่ายต่อการรวมเข้าด้วยกัน แต่มีประสิทธิภาพต่ำมาก ZBarSDK - ง่ายต่อการติดตั้งใช้งาน Google ค้นหาน้อยเพื่อค้นหาวิธี แต่มีประสิทธิภาพที่ดีจริงๆ (ไม่สแกนดาต้าเมตริกซ์และรหัสที่หายากอื่น ๆ ) ใช้งานได้ดีกับบาร์โค้ด / QRCode แต่ Scandit เป็นสิ่งที่ดีที่สุดของพวกเขาทั้งหมด เร็วสุดสแกนทุกอย่าง ราคาค่อนข้างน่าเศร้ามาก
Katafalkas

คำตอบ:


82

เราผลิตแอพพลิเคชั่น 'บาร์โค้ด' สำหรับ iPhone มันสามารถถอดรหัสรหัส QR ซอร์สโค้ดพร้อมใช้งานจากโครงการ zxing ; โดยเฉพาะคุณต้องการที่จะดูที่ที่ลูกค้า iPhoneและC ++ บางส่วนพอร์ตของห้องสมุดหลัก พอร์ตค่อนข้างเก่าจากการวางจำหน่ายโค้ด Java ประมาณ 0.9 แต่ก็ยังทำงานได้ดีพอสมควร

หากคุณต้องการสแกนรูปแบบอื่นเช่นรูปแบบ 1D คุณสามารถดำเนินการต่อพอร์ตของรหัส Java ภายในโครงการนี้เป็น C ++

แก้ไข: บาร์โค้ดและiphoneรหัสในโครงการถูกยกเลิกในช่วงต้นปี 2557


ฌอนใช้ใบอนุญาตประเภทใด ฉันต้องการสร้างแอปแบบชำระเงินที่ใช้ Zbar เป็นไปได้ภายใต้ข้อตกลงสิทธิ์การใช้งานหรือไม่
Radu

1
เพื่อให้ชัดเจนในเวลานี้ ZXing บน iPhone รองรับรหัส QR เท่านั้น?
RefuX

ฉันเชื่อว่ามีการย้ายไปที่ C ++ มากขึ้น แต่พอร์ตนั้นยังคงเป็นเสียงสะท้อนคร่าวๆของโค้ด Java อย่างน่าเสียดาย ดังนั้นใช่รองรับมากขึ้นแม้ว่าอาจจะไม่ดี
Sean Owen

ZXing สำหรับ iPhone ยังคงมีหน่วยความจำรั่วไหลโดย 1.7 ver
Yoon Lee

ฉันเข้าใจจากรายการปัญหาเกี่ยวกับคอมไพล์ของ zXing ว่าเราสามารถสแกนบาร์โค้ดในโหมดแนวนอนเท่านั้น
Sagrian

81

ตรวจสอบZBarอ่านรหัส QR และรหัส ECN / ISBN และสามารถใช้ได้ภายใต้ใบอนุญาต LGPL v2


5
ถูกต้องบางส่วน ZBar.app ได้รับใบอนุญาตภายใต้ Apache License (เวอร์ชั่น 2.0) แต่ห้องสมุดได้รับใบอนุญาตภายใต้ v2 LGPL
ฌอน

3
น่าเศร้าที่ใบอนุญาตต้องให้คุณแชร์ไฟล์วัตถุของแอปกับใครก็ตามที่ขอพวกเขา .. ลองดูzbar.sourceforge.net/iphone/sdkdoc/licensing.html
Ben Clayton

1
@BCClayton การแชร์ไฟล์ออบเจ็กต์ของแอปหมายความว่าอย่างไร
Dejell

@Odelya การส่งไฟล์. o ที่สร้างโดย Xcode ให้กับทุกคนในทางทฤษฎีช่วยให้พวกเขาสร้างแอปของคุณ ฉันไม่พอใจที่จะทำสิ่งนี้ (โดยเฉพาะอย่างยิ่งสำหรับลูกค้าของฉัน) ดังนั้น ZBar จึงไม่เป็นปัญหาสำหรับเรา หน้าการให้สิทธิ์ใช้งาน ZBar แนะนำให้คุณควร 'หวังว่าจะไม่มีใครร้องขอได้!'
Ben Clayton

@BenClayton A. ขอบคุณ B. ฉันสามารถเปลี่ยนองค์ประกอบได้ถ้ามีคนถามและต้องการผู้ใช้แอพที่ดาวน์โหลดมาแล้วเพื่อดาวน์โหลดเวอร์ชั่นใหม่ มันเพียงพอหรือไม่ C. คุณใช้ไลบรารี่ประเภทใด?
Dejell

56

เช่นเดียวกับการเปิดตัวของiOS7คุณไม่จำเป็นต้องใช้เฟรมเวิร์กหรือไลบรารีภายนอกอีกต่อไป ระบบนิเวศ iOS ด้วย AVFoundation ตอนนี้รองรับการสแกนเกือบทุกรหัสจาก QR over EAN ไปยัง UPC

เพียงดูที่Tech Noteและคู่มือการเขียนโปรแกรม AVFoundation AVMetadataObjectTypeQRCodeเป็นเพื่อนของคุณ.

นี่คือบทแนะนำที่ดีซึ่งแสดงทีละขั้นตอน: iPhone QR code scan library iOS7

ตัวอย่างเล็ก ๆ น้อย ๆ เกี่ยวกับวิธีการตั้งค่า:

#pragma mark -
#pragma mark AVFoundationScanSetup

- (void) setupScanner;
{
    self.device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

    self.input = [AVCaptureDeviceInput deviceInputWithDevice:self.device error:nil];

    self.session = [[AVCaptureSession alloc] init];

    self.output = [[AVCaptureMetadataOutput alloc] init];
    [self.session addOutput:self.output];
    [self.session addInput:self.input];

    [self.output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
    self.output.metadataObjectTypes = @[AVMetadataObjectTypeQRCode];

    self.preview = [AVCaptureVideoPreviewLayer layerWithSession:self.session];
    self.preview.videoGravity = AVLayerVideoGravityResizeAspectFill;
    self.preview.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);

    AVCaptureConnection *con = self.preview.connection;

    con.videoOrientation = AVCaptureVideoOrientationLandscapeLeft;

    [self.view.layer insertSublayer:self.preview atIndex:0];
}

1
หากคุณต้องการตรวจจับบาร์โค้ดจากภาพบน iOS8 บทช่วยสอนนี้ อาจมีประโยชน์
NSDeveloper

ฉันพบว่าฉันต้องโทรstartRunningในเซสชั่นเพื่อรับรหัสข้างต้นให้ทำงานในกรณีที่ช่วยให้ทุกคน :)
Chris

13

กล้อง iPhone 4 เป็นมากกว่าบาร์โค้ดในการทำบาร์โค้ด ห้องสมุดม้าลายข้ามบาร์โค้ดมีส้อมบน GitHub ZXing-iPhone มันเป็นโอเพ่นซอร์ส


1
โพสต์ของคุณดูเหมือนจะบอกเป็นนัยว่าพอร์ต ZXing นี้สามารถสแกนมากกว่า QRCodes หรือไม่ เป็นอย่างนั้นเหรอ?
RefuX

4
ดูเหมือนว่าส้อม github จะตายตามที่ระบุโดยปัญหานี้: github.com/joelind/zxing-iphone/issues/3
Josh Brown


10

มีห้องสมุดหลักสองแห่ง:

  • ZXingไลบรารีที่เขียนด้วย Java แล้วส่งไปยัง Objective C / C ++ (รหัส QR เท่านั้น) และอีกพอร์ตหนึ่งไปยัง ObjC ได้ถูกทำโดย TheLevelUp: ZXingObjC

  • ZBarเป็นซอฟต์แวร์โอเพ่นซอร์สสำหรับการอ่านบาร์โค้ด, อ้างอิงจาก C

จากการทดลองของฉันZBar นั้นแม่นยำและเร็วกว่า ZXing อย่างน้อยใน iPhone


ดูเหมือนว่าฉันจะ ZXingObjC เป็นคนที่ควรผลักไปด้านบนด้วยคะแนนเสียงมากที่สุดในขณะนี้ ฉันไม่ได้ใช้มันเลยแต่คำอธิบายบอกว่ามันอยู่บนความเท่าเทียมกันกับ ZXing 2.0
Shaolo

ใบอนุญาต ZBar ต้องการให้คุณเสนอไฟล์วัตถุให้กับผู้ใช้ดังนั้นพวกเขาจึงสามารถเรียกใช้และอาจแก้ไขไลบรารีของพวกเขาได้เช่นกัน
Dejell

ฉันแนะนำ ZXingObjC
Dejell


7

คุณสามารถค้นหาโซลูชัน iOS แบบเนทีฟอื่นโดยใช้Swift 4และXcode 9ที่ด้านล่าง AVFoundationกรอบดั้งเดิมที่ใช้กับในโซลูชันนี้

ส่วนแรกเป็น subclass ของซึ่งมีการติดตั้งที่เกี่ยวข้องและฟังก์ชั่นสำหรับการจัดการUIViewControllerAVCaptureSession

import UIKit
import AVFoundation

class BarCodeScannerViewController: UIViewController {

    let captureSession = AVCaptureSession()
    var videoPreviewLayer: AVCaptureVideoPreviewLayer!
    var initialized = false

    let barCodeTypes = [AVMetadataObject.ObjectType.upce,
                        AVMetadataObject.ObjectType.code39,
                        AVMetadataObject.ObjectType.code39Mod43,
                        AVMetadataObject.ObjectType.code93,
                        AVMetadataObject.ObjectType.code128,
                        AVMetadataObject.ObjectType.ean8,
                        AVMetadataObject.ObjectType.ean13,
                        AVMetadataObject.ObjectType.aztec,
                        AVMetadataObject.ObjectType.pdf417,
                        AVMetadataObject.ObjectType.itf14,
                        AVMetadataObject.ObjectType.dataMatrix,
                        AVMetadataObject.ObjectType.interleaved2of5,
                        AVMetadataObject.ObjectType.qr]

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        setupCapture()
        // set observer for UIApplicationWillEnterForeground, so we know when to start the capture session again
        NotificationCenter.default.addObserver(self,
                                           selector: #selector(willEnterForeground),
                                           name: .UIApplicationWillEnterForeground,
                                           object: nil)
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        // this view is no longer topmost in the app, so we don't need a callback if we return to the app.
        NotificationCenter.default.removeObserver(self,
                                              name: .UIApplicationWillEnterForeground,
                                              object: nil)
    }

    // This is called when we return from another app to the scanner view
    @objc func willEnterForeground() {
        setupCapture()
    }

    func setupCapture() {
        var success = false
        var accessDenied = false
        var accessRequested = false

        let authorizationStatus = AVCaptureDevice.authorizationStatus(for: .video)
        if authorizationStatus == .notDetermined {
            // permission dialog not yet presented, request authorization
            accessRequested = true
            AVCaptureDevice.requestAccess(for: .video,
                                      completionHandler: { (granted:Bool) -> Void in
                                          self.setupCapture();
            })
            return
        }
        if authorizationStatus == .restricted || authorizationStatus == .denied {
            accessDenied = true
        }
        if initialized {
            success = true
        } else {
            let deviceDiscoverySession = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera,
                                                                                        .builtInTelephotoCamera,
                                                                                        .builtInDualCamera],
                                                                          mediaType: .video,
                                                                          position: .unspecified)

            if let captureDevice = deviceDiscoverySession.devices.first {
                do {
                    let videoInput = try AVCaptureDeviceInput(device: captureDevice)
                    captureSession.addInput(videoInput)
                    success = true
                } catch {
                    NSLog("Cannot construct capture device input")
                }
            } else {
                NSLog("Cannot get capture device")
            }
        }
        if success {
            DispatchQueue.global().async {
                self.captureSession.startRunning()
                DispatchQueue.main.async {
                    let captureMetadataOutput = AVCaptureMetadataOutput()
                    self.captureSession.addOutput(captureMetadataOutput)
                    let newSerialQueue = DispatchQueue(label: "barCodeScannerQueue") // in iOS 11 you can use main queue
                    captureMetadataOutput.setMetadataObjectsDelegate(self, queue: newSerialQueue)
                    captureMetadataOutput.metadataObjectTypes = self.barCodeTypes
                    self.videoPreviewLayer = AVCaptureVideoPreviewLayer(session: self.captureSession)
                    self.videoPreviewLayer.videoGravity = .resizeAspectFill
                    self.videoPreviewLayer.frame = self.view.layer.bounds
                    self.view.layer.addSublayer(self.videoPreviewLayer)
                } 
            }
            initialized = true
        } else {
            // Only show a dialog if we have not just asked the user for permission to use the camera.  Asking permission
            // sends its own dialog to th user
            if !accessRequested {
                // Generic message if we cannot figure out why we cannot establish a camera session
                var message = "Cannot access camera to scan bar codes"
                #if (arch(i386) || arch(x86_64)) && (!os(macOS))
                    message = "You are running on the simulator, which does not hae a camera device.  Try this on a real iOS device."
                #endif
                if accessDenied {
                    message = "You have denied this app permission to access to the camera.  Please go to settings and enable camera access permission to be able to scan bar codes"
                }
                let alertPrompt = UIAlertController(title: "Cannot access camera", message: message, preferredStyle: .alert)
                let confirmAction = UIAlertAction(title: "OK", style: .default, handler: { (action) -> Void in
                    self.navigationController?.popViewController(animated: true)
                })
                alertPrompt.addAction(confirmAction)
                self.present(alertPrompt, animated: true, completion: nil)
            }
        }
    }

    func handleCapturedOutput(metadataObjects: [AVMetadataObject]) {
        if metadataObjects.count == 0 {
            return
        }

        guard let metadataObject = metadataObjects.first as? AVMetadataMachineReadableCodeObject else {
            return
        }

        if barCodeTypes.contains(metadataObject.type) {
            if let metaDataString = metadataObject.stringValue {
                captureSession.stopRunning()
                displayResult(code: metaDataString)
                return
            }
        }
    }

    func displayResult(code: String) {
        let alertPrompt = UIAlertController(title: "Bar code detected", message: code, preferredStyle: .alert)
        if let url = URL(string: code) {
            let confirmAction = UIAlertAction(title: "Launch URL", style: .default, handler: { (action) -> Void in
                UIApplication.shared.open(url, options: [:], completionHandler: { (result) in
                    if result {
                        NSLog("opened url")
                    } else {
                        let alertPrompt = UIAlertController(title: "Cannot open url", message: nil, preferredStyle: .alert)
                        let confirmAction = UIAlertAction(title: "OK", style: .default, handler: { (action) -> Void in
                        })
                        alertPrompt.addAction(confirmAction)
                        self.present(alertPrompt, animated: true, completion: {
                            self.setupCapture()
                        })
                    }
                })        
            })
            alertPrompt.addAction(confirmAction)
        }
        let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: { (action) -> Void in
            self.setupCapture()
        })
        alertPrompt.addAction(cancelAction)
        present(alertPrompt, animated: true, completion: nil)
    }

}

ส่วนที่สองคือส่วนขยายของUIViewControllerคลาสย่อยของเราAVCaptureMetadataOutputObjectsDelegateที่เราจับเอาท์พุทที่จับได้

extension BarCodeScannerViewController: AVCaptureMetadataOutputObjectsDelegate {

    func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
        handleCapturedOutput(metadataObjects: metadataObjects)
    }

}

อัปเดตสำหรับ Swift 4.2

.UIApplicationWillEnterForegroundUIApplication.willEnterForegroundNotificationการเปลี่ยนแปลงเป็น


สิ่งนี้จะให้ชื่อผลิตภัณฑ์, ขนาด, ราคา, URL ผลิตภัณฑ์, สกุลเงิน, ชื่อในการจัดเก็บ? หรือจะให้เพียงหมายเลขบาร์โค้ด @abdullahselek
R. Mohan

@ R.Mohan มันเกี่ยวข้องกับบาร์โค้ดที่คุณอ่าน โปรดตรวจสอบAVCaptureMetadataOutputและAVMetadataMachineReadableCodeObjectและลองอ่านmetadataObjectsภายในฟังก์ชันhandleCapturedOutput
abdullahselek

ตกลงจะลองทำดู ขอบคุณสำหรับการตอบกลับ @abdullahselek
R. Mohan

5

ไม่แน่ใจว่านี้จะช่วย แต่ที่นี่คือการเชื่อมโยงไปยังแหล่งที่มาเปิดห้องสมุด QR Code อย่างที่คุณเห็นคนสองคนใช้สิ่งนี้เพื่อสร้างแอพสำหรับไอโฟนแล้ว

Wikipedia มีบทความอธิบายรหัส QR คืออะไร ในความคิดของฉันรหัส QR นั้นเหมาะสำหรับวัตถุประสงค์มากกว่าบาร์โค้ดมาตรฐานที่ iphone เกี่ยวข้องเพราะถูกออกแบบมาสำหรับการใช้งานประเภทนี้


5

หากการรองรับ iPad 2 หรือ iPod Touch เป็นสิ่งสำคัญสำหรับแอปพลิเคชันของคุณฉันจะเลือก SDK สแกนเนอร์บาร์โค้ดที่สามารถถอดรหัสบาร์โค้ดในภาพที่พร่ามัวเช่นScandit บาร์โค้ดสแกนเนอร์ SDKสำหรับ iOS และ Android การถอดรหัสภาพบาร์โค้ดที่พร่ามัวก็มีประโยชน์ในโทรศัพท์ที่มีกล้องออโต้โฟกัสเพราะผู้ใช้ไม่ต้องรอให้ระบบโฟกัสอัตโนมัติเริ่มต้นทำงาน

Scandit มาพร้อมกับแผนราคาชุมชนฟรีและยังมี API ผลิตภัณฑ์ที่ทำให้ง่ายต่อการแปลงหมายเลขบาร์โค้ดเป็นชื่อผลิตภัณฑ์

(ข้อจำกัดความรับผิดชอบ: ฉันเป็นผู้ร่วมก่อตั้ง Scandit)


4

คุณมีประสบการณ์เกี่ยวกับแอพนี้อย่างไร สำหรับฉันมันใช้เวลา 10 วินาทีหรือมากกว่านั้นในการถอดรหัสบาร์โค้ด datamatrix ที่เรียบง่าย!
iamj4de

1
ลิงก์ถูกเปลี่ยนเป็นstefan.hafeneger.name/blog/2009/09/08/…
Suresh Varma

1
ลิงก์โดยตรง (ฉันไม่คิดว่า Google จะหายไปชั่วขณะ) code.google.com/p/barcodeapp

ไม่มีใครรู้ชื่อแอป Stefan ชื่ออย่างเป็นทางการใน appstore? ฉันต้องการดาวน์โหลดก่อนที่ฉันจะดำดิ่งลงไปในรหัสจริง
macutan

3

ปัญหาเกี่ยวกับกล้องของ iPhone คือรุ่นแรก (ซึ่งมีการใช้งานหลายตัน) มีกล้องโฟกัสคงที่ที่ไม่สามารถถ่ายภาพในระยะโฟกัสภายใต้ระยะ 2 ฟุต ภาพพร่ามัวและผิดเพี้ยนและหากนำมาจากระยะไกลจะมีรายละเอียด / ข้อมูลจากบาร์โค้ดไม่เพียงพอ

มี บริษัท ไม่กี่แห่งที่พัฒนาแอพของ iPhone ที่สามารถรองรับสิ่งนั้นได้โดยใช้เทคโนโลยีลดการเบลอขั้นสูง แอปพลิเคชันเหล่านั้นที่คุณสามารถพบได้ใน Apple app store: pic2shop, RedLaser และ ShopSavvy บริษัท ทั้งหมดได้ประกาศว่าพวกเขายังมี SDK อยู่ด้วย - บางอันสำหรับข้อกำหนดฟรีหรือสิทธิพิเศษมากมาย


ฉันพยายามใช้ ShopSavvy กับ iphone 3G มันสนุก แต่ก็ล้มเหลวบ่อยมากและมีช่วงเวลาที่ยากลำบากมากในการอ่านบาร์โค้ดที่ชัดเจนและชัดเจน
James Moore

1
และฉันก็ลอง pic2shop อ้างจากคู่หมั้นของฉัน: "นี่ควรจะทำให้ชีวิตของเราง่ายขึ้นได้อย่างไร" มันเป็นแอพที่น่ารัก แต่จริงๆแล้วมันไม่สามารถอ่านบาร์โค้ดได้เท่าที่ฉันจะบอกได้
James Moore

คุณพยายามอ่านรูปแบบใด ฉันพยายามใช้ pic2shop เพื่อสแกน EAN และทำงานได้ดีมาก ค่าธรรมเนียมใบอนุญาตมีราคาแพงแม้ว่ามากกว่า RedLaser
iamj4de

2

ด้วยSwift 5มันง่ายและเร็วสุด ๆ !!

คุณเพียงแค่ต้องเพิ่มฝักโกโก้ "BarcodeScanner" นี่คือรหัสเต็ม

source 'https://github.com/CocoaPods/Specs.git' 
platform :ios, '12.0' 
target 'Simple BarcodeScanner' 
do   
pod 'BarcodeScanner' 
end

ตรวจสอบให้แน่ใจว่าเพิ่มสิทธิ์กล้องในไฟล์. plist ของคุณ

<key>NSCameraUsageDescription</key>
<string>Camera usage description</string>

และเพิ่มสแกนเนอร์และจัดการผลลัพธ์ใน ViewController ของคุณด้วยวิธีนี้

import UIKit
import BarcodeScanner

class ViewController: UIViewController, BarcodeScannerCodeDelegate, BarcodeScannerErrorDelegate, BarcodeScannerDismissalDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()

        let viewController = BarcodeScannerViewController()
        viewController.codeDelegate = self
        viewController.errorDelegate = self
        viewController.dismissalDelegate = self

        present(viewController, animated: true, completion: nil)
    }

    func scanner(_ controller: BarcodeScannerViewController, didCaptureCode code: String, type: String) {
        print("Product's Bar code is :", code)
        controller.dismiss(animated: true, completion: nil)
    }

    func scanner(_ controller: BarcodeScannerViewController, didReceiveError error: Error) {
        print(error)
    }

    func scannerDidDismiss(_ controller: BarcodeScannerViewController) {
        controller.dismiss(animated: true, completion: nil)
    }
}

ยังและคำถามหรือความท้าทายใด ๆโปรดตรวจสอบตัวอย่างการใช้งานที่นี่ด้วยรหัสที่มาแบบเต็ม



1

ฉันเชื่อว่าสิ่งนี้สามารถทำได้โดยใช้ AVFramework นี่คือตัวอย่างโค้ดที่จะทำ

import UIKit
import AVFoundation

class ViewController: UIViewController, AVCaptureMetadataOutputObjectsDelegate
{

    @IBOutlet weak var lblQRCodeResult: UILabel!
    @IBOutlet weak var lblQRCodeLabel: UILabel!

    var objCaptureSession:AVCaptureSession?
    var objCaptureVideoPreviewLayer:AVCaptureVideoPreviewLayer?
    var vwQRCode:UIView?

    override func viewDidLoad() {
        super.viewDidLoad()
        self.configureVideoCapture()
        self.addVideoPreviewLayer()
        self.initializeQRView()
    }

    func configureVideoCapture() {
        let objCaptureDevice = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
        var error:NSError?
        let objCaptureDeviceInput: AnyObject!
        do {
            objCaptureDeviceInput = try AVCaptureDeviceInput(device: objCaptureDevice) as AVCaptureDeviceInput

        } catch let error1 as NSError {
            error = error1
            objCaptureDeviceInput = nil
        }
        objCaptureSession = AVCaptureSession()
        objCaptureSession?.addInput(objCaptureDeviceInput as! AVCaptureInput)
        let objCaptureMetadataOutput = AVCaptureMetadataOutput()
        objCaptureSession?.addOutput(objCaptureMetadataOutput)
        objCaptureMetadataOutput.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue())
        objCaptureMetadataOutput.metadataObjectTypes = [AVMetadataObjectTypeQRCode]
    }

    func addVideoPreviewLayer() {
        objCaptureVideoPreviewLayer = AVCaptureVideoPreviewLayer(session: objCaptureSession)
        objCaptureVideoPreviewLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill
        objCaptureVideoPreviewLayer?.frame = view.layer.bounds
        self.view.layer.addSublayer(objCaptureVideoPreviewLayer!)
        objCaptureSession?.startRunning()
        self.view.bringSubviewToFront(lblQRCodeResult)
        self.view.bringSubviewToFront(lblQRCodeLabel)
    }

    func initializeQRView() {
        vwQRCode = UIView()
        vwQRCode?.layer.borderColor = UIColor.redColor().CGColor
        vwQRCode?.layer.borderWidth = 5
        self.view.addSubview(vwQRCode!)
        self.view.bringSubviewToFront(vwQRCode!)
    }

    func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!) {
        if metadataObjects == nil || metadataObjects.count == 0 {
            vwQRCode?.frame = CGRectZero
            lblQRCodeResult.text = "QR Code wans't found"
            return
        }
        let objMetadataMachineReadableCodeObject = metadataObjects[0] as! AVMetadataMachineReadableCodeObject
        if objMetadataMachineReadableCodeObject.type == AVMetadataObjectTypeQRCode {
            let objBarCode = objCaptureVideoPreviewLayer?.transformedMetadataObjectForMetadataObject(objMetadataMachineReadableCodeObject as AVMetadataMachineReadableCodeObject) as! AVMetadataMachineReadableCodeObject
            vwQRCode?.frame = objBarCode.bounds;
            if objMetadataMachineReadableCodeObject.stringValue != nil {
                lblQRCodeResult.text = objMetadataMachineReadableCodeObject.stringValue
            }
        }
    }
}

1

นี่คือรหัสง่ายๆ:

func scanbarcode()
{
    view.backgroundColor = UIColor.blackColor()
    captureSession = AVCaptureSession()

    let videoCaptureDevice = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
    let videoInput: AVCaptureDeviceInput

    do {
        videoInput = try AVCaptureDeviceInput(device: videoCaptureDevice)
    } catch {
        return
    }

    if (captureSession.canAddInput(videoInput)) {
        captureSession.addInput(videoInput)
    } else {
        failed();
        return;
    }

    let metadataOutput = AVCaptureMetadataOutput()

    if (captureSession.canAddOutput(metadataOutput)) {
        captureSession.addOutput(metadataOutput)

        metadataOutput.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue())
        metadataOutput.metadataObjectTypes = [AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypePDF417Code]
    } else {
        failed()
        return
    }

    previewLayer = AVCaptureVideoPreviewLayer(session: captureSession);
    previewLayer.frame = view.layer.bounds;
    previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
    view.layer.addSublayer(previewLayer);
    view.addSubview(closeBtn)
    view.addSubview(backimg)

    captureSession.startRunning();

}
override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

func failed() {
    let ac = UIAlertController(title: "Scanning not supported", message: "Your device does not support scanning a code from an item. Please use a device with a camera.", preferredStyle: .Alert)
    ac.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
    presentViewController(ac, animated: true, completion: nil)
    captureSession = nil
}

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)

    if (captureSession?.running == false) {
        captureSession.startRunning();
    }
}

override func viewWillDisappear(animated: Bool) {
    super.viewWillDisappear(animated)

    if (captureSession?.running == true) {
        captureSession.stopRunning();
    }
}

func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!) {
    captureSession.stopRunning()

    if let metadataObject = metadataObjects.first {
        let readableObject = metadataObject as! AVMetadataMachineReadableCodeObject;

        AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate))
        foundCode(readableObject.stringValue);
    }

   // dismissViewControllerAnimated(true, completion: nil)
}

func foundCode(code: String) {
    var createAccountErrorAlert: UIAlertView = UIAlertView()
    createAccountErrorAlert.delegate = self
    createAccountErrorAlert.title = "Alert"
    createAccountErrorAlert.message = code
    createAccountErrorAlert.addButtonWithTitle("ok")
    createAccountErrorAlert.addButtonWithTitle("Retry")
    createAccountErrorAlert.show()
    NSUserDefaults.standardUserDefaults().setObject(code, forKey: "barcode")
    NSUserDefaults.standardUserDefaults().synchronize()
    ItemBarcode = code
    print(code)
}

override func prefersStatusBarHidden() -> Bool {
    return true
}

override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
    return .Portrait
}

1

หากคุณกำลังพัฒนาสำหรับ iOS> 10.2 ด้วย Swift 4 คุณสามารถลองใช้โซลูชันของฉันได้ ผมผสมขึ้นนี้และนี้กวดวิชาและมาพร้อมกับ ViewController ซึ่งจะสแกน QR Code ได้และprint()มันออกมา ฉันยังมีสวิตช์ใน UI ของฉันเพื่อสลับแสงกล้องอาจเป็นประโยชน์เช่นกัน สำหรับตอนนี้ฉันทดสอบบน iPhone SE เท่านั้นโปรดแจ้งให้เราทราบหากใช้งานไม่ได้กับ iPhone รุ่นใหม่

ไปเลย:

import UIKit
import AVFoundation

class QRCodeScanner: UIViewController, AVCaptureMetadataOutputObjectsDelegate {

    let captureSession: AVCaptureSession = AVCaptureSession()
    var videoPreviewLayer: AVCaptureVideoPreviewLayer?
    let qrCodeFrameView: UIView = UIView()
    var captureDevice: AVCaptureDevice?

    override func viewDidLoad() {
        // Get the back-facing camera for capturing videos
        let deviceDiscoverySession = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera, .builtInDualCamera], mediaType: AVMediaType.video, position: .back)

        captureDevice = deviceDiscoverySession.devices.first
        if captureDevice == nil {
            print("Failed to get the camera device")
            return
        }

        do {
            // Get an instance of the AVCaptureDeviceInput class using the previous device object.
            let input = try AVCaptureDeviceInput(device: captureDevice!)

            // Set the input device on the capture session.
            captureSession.addInput(input)

            // Initialize a AVCaptureMetadataOutput object and set it as the output device to the capture session.
            let captureMetadataOutput = AVCaptureMetadataOutput()
            captureSession.addOutput(captureMetadataOutput)

            // Set delegate and use the default dispatch queue to execute the call back
            captureMetadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
            captureMetadataOutput.metadataObjectTypes = [AVMetadataObject.ObjectType.qr]

            // Initialize the video preview layer and add it as a sublayer to the viewPreview view's layer.

            videoPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)

            if let videoPreviewLayer = videoPreviewLayer {
                videoPreviewLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
                videoPreviewLayer.frame = view.layer.bounds
                view.layer.addSublayer(videoPreviewLayer)

                // Start video capture.
                captureSession.startRunning()

                if let hasFlash = captureDevice?.hasFlash, let hasTorch = captureDevice?.hasTorch {
                    if hasFlash && hasTorch {
                        view.bringSubview(toFront: bottomBar)
                        try captureDevice?.lockForConfiguration()
                    }
                }
            }

            // QR Code Overlay
            qrCodeFrameView.layer.borderColor = UIColor.green.cgColor
            qrCodeFrameView.layer.borderWidth = 2
            view.addSubview(qrCodeFrameView)
            view.bringSubview(toFront: qrCodeFrameView)

        } catch {
            // If any error occurs, simply print it out and don't continue any more.
            print("Error: \(error)")
            return
        }
    }

    // MARK: Buttons and Switch

    @IBAction func switchFlashChanged(_ sender: UISwitch) {
        do {
            if sender.isOn {
                captureDevice?.torchMode = .on
            } else {
                captureDevice?.torchMode = .off
            }
        }
    }

    // MARK: AVCaptureMetadataOutputObjectsDelegate

    func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {

        // Check if the metadataObjects array is not nil and it contains at least one object.
        if metadataObjects.count == 0 {
            qrCodeFrameView.frame = CGRect.zero
            return
        }

        // Get the metadata object.
        let metadataObj = metadataObjects[0] as! AVMetadataMachineReadableCodeObject

        if metadataObj.type == AVMetadataObject.ObjectType.qr {
            // If the found metadata is equal to the QR code metadata then update the status label's text and set the bounds
            let barCodeObject = videoPreviewLayer?.transformedMetadataObject(for: metadataObj)
            qrCodeFrameView.frame = barCodeObject!.bounds

            print("QR Code: \(metadataObj.stringValue)")
        }
    }
}

0

บางครั้งก็จะมีประโยชน์ยังเพื่อสร้างรหัส QR มีห้องสมุด C ที่ยอดเยี่ยมสำหรับสิ่งนี้ซึ่งทำงานเหมือนมีเสน่ห์ มันถูกเรียกว่าlibqrencode การเขียนมุมมองที่กำหนดเองเพื่อแสดงรหัส QR นั้นไม่ยากและสามารถทำได้ด้วยความเข้าใจพื้นฐานของ QuartzCore


คุณรู้เกี่ยวกับการสอนเกี่ยวกับวิธีรวมสิ่งนี้ไว้ในโครงการ iOS xCode หรือไม่?
James

คุณต้องการแบ่งปันวิธีสร้างมุมมองโดยใช้ควอร์คอร์หรือไม่? จะเป็นเครื่องประหยัดเวลาขนาดใหญ่: P
ThomasRS

ถูกต้องแล้ว. อย่างไรก็ตามตรวจสอบให้แน่ใจว่าคุณปฏิบัติตามลิขสิทธิ์ซอฟต์แวร์แล้วห้องสมุดดังกล่าวได้รับการเผยแพร่ด้วย
GorillaPatch

คำถามนี้เกี่ยวกับการจดจำไม่ใช่รุ่น
MonsieurDart

0

คุณสามารถตรวจสอบ ZBarSDK เพื่ออ่านรหัส QR และรหัส ECN / ISBN ได้ง่ายด้วยการรวมลองรหัสต่อไปนี้

- (void)scanBarcodeWithZBarScanner
  {
// ADD: present a barcode reader that scans from the camera feed
ZBarReaderViewController *reader = [ZBarReaderViewController new];
reader.readerDelegate = self;
reader.supportedOrientationsMask = ZBarOrientationMaskAll;

ZBarImageScanner *scanner = reader.scanner;
// TODO: (optional) additional reader configuration here

// EXAMPLE: disable rarely used I2/5 to improve performance
 [scanner setSymbology: ZBAR_I25
               config: ZBAR_CFG_ENABLE
                   to: 0];

//Get the return value from controller
[reader setReturnBlock:^(BOOL value) {

}

และใน didFinishPickingMediaWithInfo เราได้รับค่าบาร์โค้ด

    - (void) imagePickerController: (UIImagePickerController*) reader
   didFinishPickingMediaWithInfo: (NSDictionary*) info
   {
    // ADD: get the decode results
    id<NSFastEnumeration> results =
    [info objectForKey: ZBarReaderControllerResults];
    ZBarSymbol *symbol = nil;
    for(symbol in results)
    // EXAMPLE: just grab the first barcode
    break;

    // EXAMPLE: do something useful with the barcode data
    barcodeValue = symbol.data;

    // EXAMPLE: do something useful with the barcode image
    barcodeImage =   [info objectForKey:UIImagePickerControllerOriginalImage];
    [_barcodeIV setImage:barcodeImage];

    //set the values for to TextFields
    [self setBarcodeValue:YES];

    // ADD: dismiss the controller (NB dismiss from the *reader*!)
    [reader dismissViewControllerAnimated:YES completion:nil];
   }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.