如何限制API调用的数量?

时间:2016-12-19 01:56:03

标签: ios swift swift3

我有一个阅读条形码的应用程序。如果检测到条形码,它将使用API​​获取有关检测到的元数据的信息。问题是,在每次扫描时,它实际上读取条码30-40次,这可能是一个问题,因为我每小时只允许进行1000次API调用。

有一种简单的方法可以在处理扫描或API调用时“暂停”扫描或API调用吗?

override func viewDidLoad() {
    super.viewDidLoad()

  // Get an instance of the AVCaptureDevice class to initialize a device object and provide the video as the media type parameter.
  let captureDevice = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)

  let yellow1 = UIColor(red: 0.427, green: 0.429, blue: 0.144, alpha: 1.0)

  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)

    // 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 = 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()

    view.bringSubview(toFront: messageLabel)
    view.bringSubview(toFront: leftBracket)
    view.bringSubview(toFront: rightBracket)


    // Initialize QR Code Frame to highlight the QR code
    qrCodeFrameView = UIView()

    if let qrCodeFrameView = qrCodeFrameView {
      qrCodeFrameView.layer.borderColor = yellow1.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)
    return
  }

    // Do any additional setup after loading the view.
}


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 barcode detected"
      return
    }

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

    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 bounds
      let barCodeObject = videoPreviewLayer?.transformedMetadataObject(for: metadataObj)
      qrCodeFrameView?.frame = barCodeObject!.bounds

      if metadataObj.stringValue != nil {
        messageLabel.text = metadataObj.stringValue
        barcodeString = (metadataObj.stringValue)
        barcodeString.remove(at: barcodeString.startIndex)
        self.readCode(barcodeString: barcodeString)

      }
    }
}

func readCode(barcodeString: String){

    let string = "https://api.nal.usda.gov/ndb/search/?format=json&q=" + barcodeString + "&sort=n&max=25&offset=0&api_key=NY4LT5Gtc9X4eOOm40UBuSqfaO2eUgcwz20jIQLn"
    let url = URL(string: string)
    URLSession.shared.dataTask(with: url!, completionHandler: {
      (data, response, error) in
      if(error != nil){
        print("object not in database")
      }else{
        do{

          let json = try JSONSerialization.jsonObject(with: data!, options:.allowFragments) as! [String : AnyObject]
          let array = json as NSDictionary

          if array["list"] != nil{

            let list = array["list"] as! [String : AnyObject]
            let item = list["item"] as! NSArray
            let dict = item[0] as! [String : AnyObject]
            let num = dict["ndbno"] as! String
            // Second API call
            self.secondAPICall(number: num)

          }
          else{

            // DO THIS IF ITEM NOT IN DATABASE
            self.itemNotInDatabase()

          }

        }catch let error as NSError{
          print(error)
        }
      }
    }).resume()
}

2 个答案:

答案 0 :(得分:6)

成功捕获条形码后,在if metadataObj.stringValue != nil区块中,您应该将委托设置为nil或captureSession设置为nil,这将暂时停止扫描(否则,它将继续扫描)。在您调用api并返回之后,如果您想要进行另一次扫描,则可以再次启动会话。

答案 1 :(得分:0)

上面的答案是正确的,我在检测到条形码时停止了捕获会话,这似乎限制了每次条形码扫描的一次通话。

    if metadataObj.stringValue != nil {
    messageLabel.text = metadataObj.stringValue
    barcodeString = (metadataObj.stringValue)
    barcodeString.remove(at: barcodeString.startIndex)
    self.readCode(barcodeString: barcodeString)
    captureSession?.stopRunning()
    }