iOS에서 바코드를 스캔하려면 어떻게해야합니까?


189

iPhone 및 / 또는 iPad에서 바코드를 간단히 스캔하려면 어떻게해야합니까?


7
슬프게도, 아이폰 카메라는 렌즈의 초점이 ∞로 고정되어 있기 때문에 현재 바코드를 읽는 데 끔찍합니다. 그래도 행운을 빈다!
Alastair Stuart 12

1
이 문제를 해결하기 위해 관찰 한 내용을 작성했습니다. 몇 가지 옵션을 테스트했습니다. RSBarcodes_Swift-통합하기 쉽지만 성능이 매우 낮습니다. ZBarSDK-구현하기도 쉬웠으며 altho에서 검색하는 방법은 거의 없었습니다. 그러나 실제로 성능이 좋았습니다 (데이터 매트릭스 및 기타 희귀 코드를 스캔하지 않았습니다)는 바코드 / QRCode에서 실제로 잘 작동합니다. 그러나 Scandit은 그들 중 최고였습니다. 초고속으로 모든 것을 스캔합니다. 슬프게도 많은 비용이 듭니다.
Katafalkas

답변:


82

iPhone 용 '바코드'응용 프로그램을 제작했습니다. QR 코드를 해독 할 수 있습니다. 소스 코드는 zxing 프로젝트 에서 사용 가능합니다 . 특히, iPhone 클라이언트핵심 라이브러리부분 C ++ 포트를 살펴보고 싶습니다 . 포트는 Java 코드의 0.9 릴리스부터 약간 오래되었지만 여전히 잘 작동합니다.

1D 형식과 같은 다른 형식을 스캔해야하는 경우이 프로젝트 내의 Java 코드 포트를 C ++로 계속 사용할 수 있습니다.

편집 : iphone프로젝트 의 바코드와 코드는 2014 년 초에 폐기되었습니다.


Sean은 어떤 종류의 라이센스를 사용합니까? Zbar를 사용하는 유료 앱을 만들고 싶습니다. 라이센스 계약에 따라 가능합니까?
Radu

1
분명히, 현재 시점에서 iPhone의 ZXing은 QR 코드 만 지원합니까?
RefuX

더 많은 것이 C ++로 포팅되었다고 생각하지만 포트는 여전히 불행히도 Java 코드의 거칠고 오래된 에코입니다. 따라서 아마도 더 잘 지원되지는 않지만 더 많이 지원됩니다.
Sean Owen

iPhone 용 ZXing의 메모리 누수는 여전히 1.7 ver입니다.
Yoon Lee

zXing의 git에있는 문제 목록에서 가로 모드에서만 바코드를 스캔 할 수 있음을 이해합니다.
Sagrian

81

확인 ZBar는 QR 코드 및 ECN / ISBN 코드를 읽고 LGPL v2로 라이선스로 사용할 수 있습니다.


5
부분적으로 맞습니다. ZBar.app는 Apache 라이센스 (버전 2.0)에 따라 라이센스가 부여 되지만 라이브러리 는 LGPL v2에 따라 라이센스가 부여됩니다.
Sean

3
슬프게도 라이센스를 요청하는 사람과 앱의 오브젝트 파일을 공유 할 필요 .. 체크 아웃 zbar.sourceforge.net/iphone/sdkdoc/licensing.html
벤 클레이튼

1
@ BenClayton 앱의 객체 파일을 공유한다는 것은 무엇을 의미합니까?
Dejell

@Odelya Xcode에서 생성 한 .o 파일을 다른 사람에게 보내 이론적으로 앱을 빌드 할 수 있습니다. ZBar는 우리에게 문제가되지 않으므로 분명히 (특히 고객의 경우)이 작업을 수행하는 것이 행복하지 않습니다. ZBar 라이센스 페이지에는 '아무도 요청하지 않기를 바랍니다!'
Ben Clayton

@ BenClayton A. 감사합니다 B. 누군가가 이미 다운로드 한 앱 사용자에게 요청하고 최신 버전을 다운로드하도록 요구하면 구성 요소를 변경할 수 있습니다. 충분한가? C. 어떤 라이브러리를 사용하고 있습니까?
Dejell

56

릴리스와 마찬가지로 iOS7더 이상 외부 프레임 워크 또는 라이브러리를 사용할 필요가 없습니다. AVFoundation이 포함 된 iOS 에코 시스템은 이제 QR over EAN에서 UPC까지 거의 모든 코드 스캔을 완벽하게 지원합니다 .

기술 노트 와 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 카메라는 바코드를 작성하는 것 이상의 역할을합니다. zebra crossing 바코드 라이브러리에는 github zxing-iphone 에 포크가 있습니다. 오픈 소스입니다.


1
귀하의 게시물 에이 ZXing 포트가 QRCodes 이상을 스캔 할 수 있다고 암시하는 것 같습니다. 그 경우입니까?
RefuX

4
이 문제에서 알 수 있듯이 github 포크가 죽은 것 같습니다 : github.com/joelind/zxing-iphone/issues/3
Josh Brown


10

두 가지 주요 라이브러리가 있습니다.

  • Java로 작성된 라이브러리를 ZXing 한 후 Objective C / C ++로 포트합니다 (QR 코드 만 해당). 그리고 TheLevelUp : ZXingObjC에 의해 ObjC에 대한 다른 포트가 수행되었습니다.

  • ZBar 는 C 기반 바코드를 읽기위한 오픈 소스 소프트웨어입니다.

내 실험에 따르면 ZBar는 적어도 iPhone에서 ZXing보다 훨씬 정확하고 빠릅니다 .


ZXingObjC는 지금까지 가장 많은 표를 얻은 상단에 올려야 할 것 같습니다. 아직 사용 하지는 않았지만 설명에 따르면 ZXing 2.0과 동일합니다.
Shaolo

ZBar 라이센스를 사용하려면 개체 파일을 사용자에게 제공하여이를 실행하고 라이브러리를 수정할 수도 있습니다.
Dejell

16:59에 ZXingObjC
Dejell


7

아래에서 Swift 4Xcode 9 를 사용하여 다른 기본 iOS 솔루션을 찾을 수 있습니다 . AVFoundation이 솔루션에서 사용되는 기본 프레임 워크입니다.

첫 번째 부분은에 대한 UIViewController설정 및 처리기 기능과 관련된 하위 클래스입니다 AVCaptureSession.

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 업데이트

.UIApplicationWillEnterForeground로 바뀝니다 UIApplication.willEnterForegroundNotification.


제품 이름, 크기, 가격, 제품 URL, 통화, 상점 이름을 제공합니까? 또는 바코드 번호 @abdullahselek
R. Mohan을 제공합니다.

@ R.Mohan 그것은 당신이 읽는 바코드와 관련이 있습니다. AVCaptureMetadataOutputAVMetadataMachineReadableCodeObject를 확인 metadataObjects하고 handleCapturedOutput 함수 내부를 읽으십시오 .
abdullahselek

알았어. 답글을 보내 주셔서 감사합니다 @abdullahselek
R. Mohan

5

이것이 도움이 될지 확실하지 않지만 여기에 오픈 소스 QR 코드 라이브러리에 대한 링크가 있습니다 . 보시다시피, 두 사람이 이미 이것을 사용하여 iPhone 용 앱을 만들었습니다.

Wikipedia에는 QR 코드가 무엇인지 설명하는 기사 있습니다. 제 생각에 QR 코드는 아이폰이 이런 유형의 구현을 위해 설계된 표준 바코드보다 목적에 훨씬 더 적합합니다.


5

응용 프로그램에 iPad 2 또는 iPod Touch 지원이 중요한 경우 iOS 및 Android 용 Scandit 바코드 스캐너 SDK 와 같이 흐릿한 이미지의 바코드를 해독 할 수있는 바코드 스캐너 SDK를 선택합니다 . 흐릿한 바코드 이미지 디코딩은 사용자가 자동 ​​초점이 시작될 때까지 기다릴 필요가 없기 때문에 자동 초점 카메라가있는 전화기에서도 유용합니다.

Scandit에는 무료 커뮤니티 가격 계획이 제공되며 바코드 번호를 제품 이름으로 쉽게 변환 할 수있는 제품 API도 있습니다.

(면책 조항 : 저는 Scandit의 공동 설립자입니다)


4

이 앱에 대한 경험이 어떻습니까? 나를 위해 간단한 데이터 매트릭스 바코드를 해독하는 데 10 초 이상이 걸립니다!
iamj4de


1
직접 링크 (Google이 한동안 사라질 것이라고 생각하지 않습니다) code.google.com/p/barcodeapp

앱 스토어에서 Stefan의 공식 명칭이 무엇인지 아는 사람이 있습니까? 실제 코드에 들어가기 전에 다운로드하고 싶습니다.
macutan

3

iPhone 카메라의 문제점은 (사용중인 톤이 많은) 첫 번째 모델에는 2 피트 미만의 거리에서 초점을 맞출 수없는 고정 초점 카메라가 있다는 것입니다. 이미지가 흐릿하고 왜곡되어 더 먼 거리에서 촬영하면 바코드의 세부 정보 / 정보가 충분하지 않습니다.

일부 회사는 고급 디 블러 링 기술을 사용하여이를 수용 할 수있는 iPhone 앱을 개발했습니다. Apple 앱 스토어에서 찾을 수있는 응용 프로그램은 pic2shop, RedLaser 및 ShopSavvy입니다. 모든 회사는 SDK를 사용할 수 있다고 발표했습니다. 일부는 무료 또는 매우 우선적 인 용어로 확인하십시오.


ShopSavvy를 3G iPhone과 함께 사용하려고했습니다. 재미 있지만 매우 자주 충돌하며 매우 깨끗하고 평평한 바코드를 읽는 데 매우 어려움이 있습니다.
James Moore

1
그리고 방금 pic2shop을 시도했습니다. 나의 약혼녀의 인용문 : "이것은 우리의 삶을 더 편하게 해줄 것입니까?" 귀여운 앱이지만 실제로 내가 알 수있는 한 바코드를 읽을 수는 없습니다.
James Moore

어떤 형식을 읽으려고 했습니까? pic2shop을 사용하여 EAN을 스캔하려고 시도했으며 매우 잘 작동합니다. 그러나 라이센스 비용은 RedLaser보다 비쌉니다.
iamj4de

2

스위프트 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

Swift 4로 iOS> 10.2를 개발하는 경우 내 솔루션을 사용해 볼 수 있습니다. 나는 혼합 자습서를하고 QR 코드와 스캔의 ViewController 함께했다 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 프로젝트에 포함시키는 방법에 대한 튜토리얼을 알고 있습니까?
제임스

quartcore를 사용하여 뷰를 생성 한 방법을 공유 하시겠습니까? P : 큰 시간을 절약 될 것이다
ThomasRS

맞아 그거야. 그러나 라이브러리가 게시 된 소프트웨어 라이센스를 준수하는지 확인하십시오.
GorillaPatch

이 질문은 세대가 아니라 인식에 관한 것입니다.
MonsieurDart

0

QR 코드와 ECN / ISBN 코드를 읽기 위해 ZBarSDK를 확인할 수 있습니다. 다음 코드를 통합하면 간단합니다.

- (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.