Tạo một máy quét Barcode/ QRCode

Bài viết sẽ giới thiệu chi tiết cách xây dựng ứng dụng quét Barcode/ QRCode từ camera của thiết bị phone

Bước 1: Tạo Scanner class

Tạo một class có tên là Scanner kế thừa NSObject và import AVFoundation.

Bước 2: Thêm các thuộc tính cho Scanner class

Chúng ta cần thêm 1 số thuộc tính sẽ được sử dụng sau.

Bước 3: Tạo AVCaptureSession

AVCaptureSession là gì? Có thể hiểu đơn giản đây là một đối tượng dùng để quản lý hoạt động chụp và điều phối luồng dữ liệu từ các thiết bị đầu vào để thu được kết quả đầu ra. Như vậy, bước đầu tiên chúng ta se thực hiện việc lấy dữ liệu từ thiết bị đầu vào. Trong class Scanner, tạo một private function là createCaptureSession và nó sẽ return về một đối tượng createCaptureSession như sau: Tiếp theo tạo một biến captureSession, biến này là một instance của AVCaptureSession. Sau đó tạo một biến captureDevice để làm đầu vào cho captureSession sau này. Code được viết như sau:

Bước 5: Tạo và thêm input, output

Đầu tiên cần phải tạo khối try catch, vì AVCaptureDeviceInput có thể tạo ra exception. Bây giờ chúng ta sẽ thêm input và output cho biến captureSession. Để làm điều này cần tạo 2 biến mới, biến thứ nhất gọi là deviceInput, biến thứ 2 là metaDataOutput. deviceInput sẽ sử dụng biến captureDevice đã khởi tạo ở bước 3 để làm đầu vào cho việc khởi tạo AVCaptureDeviceInput. metaDataOutput là một instance mới của AVCatpureMetadataOutput. Tiếp theo chúng ta sẽ thêm chúng vào captureSession như một input và output. Trước khi thêm input hoặc output cho biến captureSession thì cần phải kiểm tra xem có thể thêm được vào hay không. Nếu không thì trả về nil bởi vì nhất định phải sử dụng được cả input và output mới được. Chúng ta sẽ thêm input sau đó mới thêm output. Khi thêm output thì chúng ta cần viết thêm 1 đoạn code nữa để lấy dữ liệu từ Barcodes và QRCode mà đã được scan. deviceInput sẽ được thêm vào captureSession trong do như sau: Thêm output cũng làm tương tự. Tuy nhiên cần thêm một chút xử lý. Đầu tiên là ép kiểu viewController về AVCaptureMetadataOutputObjectsDelegate để có thể sử dụng nó như một delegate. Delegate này để chúng ta sử dụng khi nhận được thông tin từ Barcodes hoặc QRCodes mà đã scan. Sau khi ép kiểu xong thì set nó giống như một delegate cho metaDataOutput. Thêm nữa,tạo thêm phương thức metaObjectTypes để định dạng những loại type mà có thể scan được. Code được viết như sau: Vậy là đã xong hàm createCaptureSession, tổng hợp lại code cả hàm như sau:

Bước 6: Taọ metaObjectTypes

Ở bước trước chúng ta sử dụng metaObjectTypes như chưa tạo. Tạo function này cũng rất nhanh thôi, chúng ta trả về một mảng Barcodes và QRCode có thể scan là được, cụ thể như sau:

Bước 7: Tạo preview Layer

Preview layer là layer để hiển thị video stream từ camera. Cách setup khá là đơn giản. Tham số cần truyền vào là một view và một biến captureSession, sau đó hàm sẽ trả lại một AVCaptureVideoPreviewLayer. Code được viết như sau:

Bước 8: Tạo hàm khởi tạo cho class Scanner

Hàm init được tạo với 3 tham số truyền vào là viewController, view và phương thức handle ( để xử lý sau khi nhận kết quả đầu ra) Vì viewController sẽ được sử dụng như một AVCaptureMetadataOutputObjectsDelegate nên cần phải kế thừa AVCaptureMetadataOutputObjectsDelegate. view sẽ được dùng để hiện thị preview Layer (như đã tạo ở bước 7) codeOutputHandler là một hàm để chuyển giá trị nhận được từ Barcode hoặc QRCode đã được scan. Đầu tiên thì viết hàm init như sau: Sau super.init() cần phải khởi tạo captureSession. Khởi tạo preview Layer sau đó add và view giống như 1 sub layer như sau: Tổng hợp lại, hàm init được viết như sau:

Bước 9: Tạo hàm start và stop capture session

2 hàm này gọi startRunningstopRunning của đối tượng captureSesion đã tạo từ bước trước. Trước khi gọi hàm này cần phải chắc chắn captureSession không bị nil mới thực hiện được. Code được viết như sau:

Bước 10: Khởi tạo Scanner và implement delegate method

Bước này chúng ta sẽ khởi tạo Scanner và thực hiện phương thức delegate trong viewController. Cũng phải tạo một function tên là handleCode dùng để làm tham số cho codeOutputHandler khi init Scanner như sau: Tiếp theo, chúng ta tạo một instance của Scanner như sau: Trong đó, viewController chính là controller đang gọi tới scanner, view là vùng muốn hiển thị preview Layer, còn codeOutputHandler chính là hàm handleCode vừa tạo Như đã nói ở trên, viewController được sử dụng như một AVCaptureMetadataOuputObjectsDelegate, do đó cần phải kế thừa AVCaptureMetadataOuputObjectsDelegate, chú ý cần import AVFoundation Implement phương thức metadataOutput, đây là phương thức sẽ nhận dữ liệu trả về sau khi scan xong. Vì các phương thức khởi tạo đều viết trong lớp Scanner, do đó không thể sử lý trực tiếp trong controller.Vì vậy cần phải tạo một delegate trong Scanner để gọi nó. Quay laị viewController, thực hiện gọi hàm này trong metadataOutput:

Bước 11: Implement scannerDelegate

Trong function scannerDelegate sẽ thực hiện stop session. Để tránh việc gọi codeOutputHandler nhiều lần thì sau khi trả về kết quả scan chúng ta sẽ thực hiện stop session luôn. Hàm stop chúng ta đã viết ở trên, chính là hàm self.requestCaptureStopRunning(). Sau khi stop thành công, từ metadataObjects trả về, ta sẽ lấy được value như sau: Giá trị string trả về sẽ là đầu vào cho hàm codeOutputHandler. Tổng hợp lại đoạn code trong scannerDelegate như sau: Vậy là chúng ta đã hoàn thành xong các bước để scan Barcode hoặc QRCode.

Tài liệu tham khảo

Mình đã đính kèm source mẫu trong link bên dưới các bạn có thể tham khảo. https://github.com/oHaThiHoan/IOSExample.git

Còn đây là tài liệu: https://medium.com/programming-with-swift/how-to-read-a-barcode-or-qrcode-with-swift-programming-with-swift-10d4315141d2

.