我正在构建条形码扫描仪。操作很简单
扫描条形码,
如果扫描的条形码在我的firebase数据库中,则执行func updateProductInfo()
如果条形码不在我的firebase数据库中,请执行func enterNewProduct()。
我现在遇到的一个问题是如何定义metadataObj
,以便所有以及我稍后定义的任何其他函数都可以访问它。我试图在ScanController
课程的正下方定义它,但我无法弄明白。我的代码在
import UIKit
import AVFoundation
import Firebase
class ScanController: UIViewController, AVCaptureMetadataOutputObjectsDelegate {
var captureSession: AVCaptureSession?
var videoPreviewLayer: AVCaptureVideoPreviewLayer?
var qrCodeFrameView: UIView?
let itemDB = FIRDatabase.database().reference().child("Items")
let supportedCodeTypes = [AVMetadataObjectTypeUPCECode,
AVMetadataObjectTypeCode39Code,
AVMetadataObjectTypeCode39Mod43Code,
AVMetadataObjectTypeCode93Code,
AVMetadataObjectTypeCode128Code,
AVMetadataObjectTypeEAN8Code,
AVMetadataObjectTypeEAN13Code,
AVMetadataObjectTypeAztecCode,
AVMetadataObjectTypePDF417Code,
AVMetadataObjectTypeQRCode]
let messageLabel: UILabel = {
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 40))
// label.center = CGPoint(x: 160, y: 285)
label.center = CGPoint(x: 160, y: 285)
label.textAlignment = .center
return label
}()
let productDescriptionTextField: UITextField = {
let tf = UITextField()
tf.placeholder = "Product Description"
tf.translatesAutoresizingMaskIntoConstraints = false
return tf
}()
let descriptionSeparatorView: UIView = {
let view = UIView()
view.backgroundColor = UIColor(r: 220, g: 220, b: 220)
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
let priceTextField: UITextField = {
let tf = UITextField()
tf.placeholder = "Price"
tf.translatesAutoresizingMaskIntoConstraints = false
return tf
}()
let priceSeparatorView: UIView = {
let view = UIView()
view.backgroundColor = UIColor(r: 220, g: 220, b: 220)
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
let productLocationTextField: UITextField = {
let tf = UITextField()
tf.placeholder = "Product Location"
tf.translatesAutoresizingMaskIntoConstraints = false
return tf
}()
let productImageView: UIImageView = {
let imageView = UIImageView()
imageView.image = UIImage(named: "XXXXXXX")
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.contentMode = .scaleAspectFill
return imageView
}()
let exitScanButton: UIButton = {
let button = UIButton(type: .system)
button.backgroundColor = UIColor(r: 80, g: 101, b: 161)
button.setTitle("Exit", for: .normal)
button.setTitleColor(UIColor.white, for: .normal)
button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 16)
button.translatesAutoresizingMaskIntoConstraints = false
button.addTarget( nil, action: #selector(exitScan), for:.touchUpInside)
return button
}()
let newProductEntry: UIView = {
let view = UIView()
view.backgroundColor = UIColor.white
view.translatesAutoresizingMaskIntoConstraints = false
view.layer.cornerRadius = 5
view.layer.masksToBounds = true
return view
}()
let productSummary: UIView = {
let view = UIView()
view.backgroundColor = UIColor.white
view.translatesAutoresizingMaskIntoConstraints = false
view.layer.cornerRadius = 5
view.layer.masksToBounds = true
return view
}()
let productDescriptionLabel: UILabel = {
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 40))
// label.center = CGPoint(x: 160, y: 285)
label.center = CGPoint(x: 160, y: 285)
label.textAlignment = .center
return label
}()
let storeNameLabel: UILabel = {
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 40))
// label.center = CGPoint(x: 160, y: 285)
label.center = CGPoint(x: 160, y: 285)
label.textAlignment = .center
return label
}()
let verifyProductInfoButton: UIButton = {
let button = UIButton(type: .system)
button.backgroundColor = UIColor(r: 80, g: 101, b: 161)
button.setTitle("Checked", for: .normal)
button.setTitleColor(UIColor.white, for: .normal)
button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 16)
button.translatesAutoresizingMaskIntoConstraints = false
button.addTarget( nil, action: #selector(verifyNewProduct), for:.touchUpInside)
return button
}()
let updateProductInfoButton: UIButton = {
let button = UIButton(type: .system)
button.backgroundColor = UIColor(r: 80, g: 101, b: 161)
button.setTitle("Update", for: .normal)
button.setTitleColor(UIColor.white, for: .normal)
button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 16)
button.translatesAutoresizingMaskIntoConstraints = false
button.addTarget( nil, action: #selector(updateProductInfo), for:.touchUpInside)
return button
}()
let enterNewProductButton: UIButton = {
let button = UIButton(type: .system)
button.backgroundColor = UIColor(r: 80, g: 101, b: 161)
button.setTitle("Enter", for: .normal)
button.setTitleColor(UIColor.white, for: .normal)
button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 16)
button.translatesAutoresizingMaskIntoConstraints = false
button.addTarget( nil, action: #selector(enterNewProduct), for:.touchUpInside)
return button
}()
func updateProductInfo() {
guard let price = priceTextField.text,
let location = productLocationTextField.text
else{
print("Please update price and product location")
return
}
}
func verifyNewProduct() {
// need to add a counter that counts how many people verified product information
self.dismiss(animated: true, completion: nil)
}
func enterNewProduct() {
let itemID = metadataObj.stringValue
guard let Description = productDescriptionTextField.text,
let price = priceTextField.text,
let location = productLocationTextField.text
else{
print("Fill basic product information")
return
}
let ref = FIRDatabase.database().reference(fromURL: "")
// creating an item child node
let values = ["Item Description": Description, "Image": price, "Location": location, "Price": price ]
let items = ref.child("Items").child(itemID!)
items.updateChildValues(values, withCompletionBlock: { (err, ref) in
if err != nil {
print(err)
return
}
})
self.dismiss(animated: true, completion: nil)
}
func exitScan() {
//Go back to ViewController
self.dismiss(animated: true, completion: nil)
}
func setupUpdateProductInfo() {
productSummary.addSubview(productDescriptionLabel)
productSummary.addSubview(storeNameLabel)
productSummary.addSubview(priceTextField)
productSummary.addSubview(productLocationTextField)
productSummary.addSubview(verifyProductInfoButton)
productSummary.addSubview(updateProductInfoButton)
productSummary.addSubview(productImageView)
// need x, y, width, height constraints for product image
productImageView.leftAnchor.constraint(equalTo: productSummary.leftAnchor, constant: 12).isActive = true
productImageView.topAnchor.constraint(equalTo: productSummary.topAnchor).isActive = true
productImageView.widthAnchor.constraint(equalTo: productSummary.widthAnchor, constant: 100).isActive = true
productImageView.heightAnchor.constraint(equalToConstant: 100).isActive = true
// need x, y, width, height constraints for store logo
storeNameLabel.leftAnchor.constraint(equalTo: productDescriptionLabel.leftAnchor, constant: 12).isActive = true
storeNameLabel.topAnchor.constraint(equalTo: productSummary.topAnchor).isActive = true
storeNameLabel.widthAnchor.constraint(equalTo: productSummary.widthAnchor).isActive = true
// need x, y, width, height constraints for description label
productDescriptionLabel.leftAnchor.constraint(equalTo: productImageView.leftAnchor, constant: 12).isActive = true
productDescriptionLabel.topAnchor.constraint(equalTo: productSummary.topAnchor).isActive = true
productDescriptionLabel.widthAnchor.constraint(equalTo: productSummary.widthAnchor).isActive = true
productDescriptionLabel.rightAnchor.constraint(equalTo: storeNameLabel.leftAnchor,constant: 12).isActive = true
// need x, y, width, height constraints for price textfield
priceTextField.leftAnchor.constraint(equalTo: productImageView.rightAnchor, constant: 12).isActive = true
priceTextField.topAnchor.constraint(equalTo: productDescriptionLabel.bottomAnchor).isActive = true
priceTextField.widthAnchor.constraint(equalToConstant: 50).isActive = true
// need x, y, width, height constraints for location textfield
productLocationTextField.leftAnchor.constraint(equalTo: priceTextField.rightAnchor, constant: 12).isActive = true
productLocationTextField.topAnchor.constraint(equalTo: productDescriptionLabel.bottomAnchor).isActive = true
productLocationTextField.widthAnchor.constraint(equalToConstant: 50).isActive = true
}
func setupNewProductEntry() {
newProductEntry.addSubview(productImageView)
newProductEntry.addSubview(productLocationTextField)
newProductEntry.addSubview(productDescriptionTextField)
newProductEntry.addSubview(priceTextField)
newProductEntry.addSubview(enterNewProductButton)
newProductEntry.addSubview(descriptionSeparatorView)
newProductEntry.addSubview(priceSeparatorView)
// need x, y, width, height constraints
newProductEntry.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
newProductEntry.topAnchor.constraint(equalTo: view.topAnchor, constant: 100).isActive = true
newProductEntry.widthAnchor.constraint(equalTo: view.widthAnchor, constant: -24).isActive = true
newProductEntry.heightAnchor.constraint(equalToConstant: 150).isActive = true
// need x, y, width, height constraints for name productDescriptionTextField
productDescriptionTextField.leftAnchor.constraint(equalTo: newProductEntry.leftAnchor, constant: 12).isActive = true
productDescriptionTextField.topAnchor.constraint(equalTo: newProductEntry.topAnchor).isActive = true
productDescriptionTextField.widthAnchor.constraint(equalTo: newProductEntry.widthAnchor).isActive = true
// need x, y, width, height constraints for description separator line
descriptionSeparatorView.leftAnchor.constraint(equalTo: newProductEntry.leftAnchor).isActive = true
descriptionSeparatorView.topAnchor.constraint(equalTo: productDescriptionTextField.bottomAnchor).isActive = true
descriptionSeparatorView.widthAnchor.constraint(equalTo: newProductEntry.widthAnchor).isActive = true
descriptionSeparatorView.heightAnchor.constraint(equalToConstant: 1).isActive = true
// need x, y, width, height constraints for name pricetextfield
priceTextField.leftAnchor.constraint(equalTo: newProductEntry.leftAnchor, constant: 12).isActive = true
priceTextField.topAnchor.constraint(equalTo: productDescriptionTextField.bottomAnchor).isActive = true
priceTextField.widthAnchor.constraint(equalTo: newProductEntry.widthAnchor).isActive = true
// need x, y, width, height constraints for price separator line
priceSeparatorView.leftAnchor.constraint(equalTo: newProductEntry.leftAnchor).isActive = true
priceSeparatorView.topAnchor.constraint(equalTo: priceTextField.bottomAnchor).isActive = true
priceSeparatorView.widthAnchor.constraint(equalTo: newProductEntry.widthAnchor).isActive = true
priceSeparatorView.heightAnchor.constraint(equalToConstant: 1).isActive = true
// need x, y, width, height constraints for name LocationTextField
productLocationTextField.leftAnchor.constraint(equalTo: newProductEntry.leftAnchor, constant: 12).isActive = true
productLocationTextField.topAnchor.constraint(equalTo: priceTextField.bottomAnchor).isActive = true
productLocationTextField.widthAnchor.constraint(equalTo: newProductEntry.widthAnchor).isActive = true
}
func setupenterNewProductButton(){
// need x, y, width, height constraints
enterNewProductButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
enterNewProductButton.topAnchor.constraint(equalTo: newProductEntry.bottomAnchor, constant: 12).isActive = true
enterNewProductButton.widthAnchor.constraint(equalTo: newProductEntry.widthAnchor).isActive = true
enterNewProductButton.heightAnchor.constraint(equalToConstant: (50)).isActive = true
}
func setupupdateProductInfoButton(){
// need x, y, width, height constraints
updateProductInfoButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
updateProductInfoButton.topAnchor.constraint(equalTo: productSummary.bottomAnchor, constant: 12).isActive = true
updateProductInfoButton.widthAnchor.constraint(equalTo: productSummary.widthAnchor).isActive = true
updateProductInfoButton.heightAnchor.constraint(equalToConstant: (50)).isActive = true
}
func setupverifyProductInfoButton(){
// need x, y, width, height constraints
verifyProductInfoButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
verifyProductInfoButton.topAnchor.constraint(equalTo: productSummary.bottomAnchor, constant: 12).isActive = true
verifyProductInfoButton.widthAnchor.constraint(equalTo: productSummary.widthAnchor).isActive = true
verifyProductInfoButton.heightAnchor.constraint(equalToConstant: (50)).isActive = true
verifyProductInfoButton.leftAnchor.constraint(equalTo: enterNewProductButton.rightAnchor).isActive = true
}
override func viewDidLoad() {
super.viewDidLoad()
//Get an instance of the AVCaptureDevice class a device object and provide the video as the media type parameter
let captureDevice = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)
do {
// Get an instance of the AVCaptureDeviceInput class using the previous device object.
let input = try AVCaptureDeviceInput(device: captureDevice)
// Initialize the captureSession object.
captureSession = AVCaptureSession()
// Set the input device on the capture session.
captureSession?.addInput(input)
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 = supportedCodeTypes
// Initialize the video preview layer and add it as a sublayer to the viewPreview view's layer.
videoPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
videoPreviewLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill
videoPreviewLayer?.frame = view.layer.bounds
view.layer.addSublayer(videoPreviewLayer!)
// Start video capture.
captureSession?.startRunning()
// Add the message label
self.view.addSubview(messageLabel)
self.view.addSubview(exitScanButton)
setupexitScanButton()
//initialize QR Code Frame to highlight the QR Code
qrCodeFrameView = UIView()
if let qrCodeFrameView = qrCodeFrameView {
qrCodeFrameView.layer.borderColor = UIColor.green.cgColor
qrCodeFrameView.layer.borderWidth = 2
view.addSubview(qrCodeFrameView)
}
} catch {
// If any error occurs, simply print it out and don't continue any more.
print(error)
return
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!) {
// Check if the metadataObjects array is not nil and it contains at least one object.
if metadataObjects == nil || metadataObjects.count == 0 {
qrCodeFrameView?.frame = CGRect.zero
messageLabel.text = "No QR/barcode is detected"
return
}
//Get metadata object
let metadataObj = metadataObjects[0] as! AVMetadataMachineReadableCodeObject
let itemID = metadataObj.stringValue
if supportedCodeTypes.contains(metadataObj.type) {
//if the found metadata is equal to the QR code metadata then update the status label's text and set the the bounds
let barCodeObject = videoPreviewLayer?.transformedMetadataObject(for: metadataObj)
qrCodeFrameView?.frame = barCodeObject!.bounds
if metadataObj.stringValue != nil {
messageLabel.text = metadataObj.stringValue
//Searches firebase for existing barcode
let itemToSearchFor = metadataObj.stringValue
FIRDatabase.database().reference().child("Items").child(itemToSearchFor!).observeSingleEvent(of: .value, with:{(snap) in
print(snap)
}) } else {
setupNewProductEntry()
}
}
}
func setupexitScanButton() {
// need x, y, width, height constraints
exitScanButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
exitScanButton.topAnchor.constraint(equalTo: view.topAnchor, constant: 12).isActive = true
exitScanButton.widthAnchor.constraint(equalToConstant: 60).isActive = true
exitScanButton.heightAnchor.constraint(equalToConstant: (50)).isActive = true
}
}
我的错误目前位于let itemID = metadataObj.stringValue
。
答案 0 :(得分:0)
在qrcodeframeview的顶部定义它,使其在您的班级中“全局”