我正在制作有关图书的应用程序。
在应用程式中
我想通过获取ISBN(条形码)来使应用自动填充图书信息

views

有2个 class 。
一个是“UploadMain”,另一个是“ScanView”

我可以通过扫描来获取ISBN,
但我在将数据从ScanView传递到UploadMain时遇到问题。

在ScanView中,我使用了如下所示的可选绑定

if let UploadVC = self.storyboard?.instantiateViewControllerWithIdentifier("UploadMain") as? UploadMain {
     UploadVC.ISBNstring = self.detectionString!
}

UploadMain类的代码
override func viewDidLoad(){
    super.viewDidLoad()
    ISBN.delegate = self

}

override func viewWillAppear(animated: Bool){
    ISBN.text = ISBNstring
}

我不知道我的代码有什么问题。

的完整代码UploadMain
import UIKit
import Foundation

class UploadMain: UIViewController,UITextFieldDelegate {


var ISBNstring: String = ""
var TitleString: String = ""
var AuthorString: String = ""
var PubString: String = ""
var PriceSting: String = ""

@IBOutlet weak var ISBN: UITextField!

@IBOutlet weak var bookTitle: UITextField!

@IBOutlet weak var bookAuthor: UITextField!

@IBOutlet weak var bookPub: UITextField!

@IBOutlet weak var bookPrice: UITextField!



override func viewDidLoad(){
    super.viewDidLoad()
    ISBN.delegate = self
}

override func viewWillAppear(animated: Bool){
    ISBN.text = ISBNstring
}



@IBAction func Upload(sender: AnyObject) {
    dismissViewControllerAnimated(true, completion: nil)
}
}

ScanView类
import UIKit
import AVFoundation
import Foundation


class ScanView : UIViewController, AVCaptureMetadataOutputObjectsDelegate {



let session         : AVCaptureSession = AVCaptureSession()
var previewLayer    : AVCaptureVideoPreviewLayer!
var detectionString : String!
let apiKey : String = "---------dddddd"


override func viewDidLoad() {
    super.viewDidLoad()

    // For the sake of discussion this is the camera
    let device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)

    // Create a nilable NSError to hand off to the next method.
    // Make sure to use the "var" keyword and not "let"
    var error : NSError? = nil
    var input: AVCaptureDeviceInput = AVCaptureDeviceInput()
    do {
        input = try  AVCaptureDeviceInput(device: device) as AVCaptureDeviceInput
    } catch let myJSONError {
        print(myJSONError)
    }

    // If our input is not nil then add it to the session, otherwise we're kind of done!
    if input !=  AVCaptureDeviceInput() {
        session.addInput(input)
    }
    else {
        // This is fine for a demo, do something real with this in your app. :)
        print(error)
    }

    let output = AVCaptureMetadataOutput()
    output.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue())
    session.addOutput(output)
    output.metadataObjectTypes = output.availableMetadataObjectTypes


    previewLayer = AVCaptureVideoPreviewLayer(session: session)
    previewLayer.frame = self.view.bounds
    previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
    self.view.layer.addSublayer(previewLayer)

    // Start the scanner. You'll have to end it yourself later.
    session.startRunning()

}



// This is called when we find a known barcode type with the camera.
func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!) {

    var highlightViewRect = CGRectZero
    var barCodeObject : AVMetadataObject!
    let barCodeTypes = [AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code]


    // The scanner is capable of capturing multiple 2-dimensional barcodes in one scan.
    for metadata in metadataObjects {

        for barcodeType in barCodeTypes {

            if metadata.type == barcodeType {
                barCodeObject = self.previewLayer.transformedMetadataObjectForMetadataObject(metadata as! AVMetadataMachineReadableCodeObject)

                highlightViewRect = barCodeObject.bounds

                detectionString = (metadata as! AVMetadataMachineReadableCodeObject).stringValue

                self.session.stopRunning()

                self.alert(detectionString)

                // Daum Book API 호출
                let apiURI = NSURL(string: "https://apis.daum.net/search/book?apikey=\(apiKey)&q=\(detectionString)&searchType=isbn&output=json")

                let apidata : NSData? = NSData(contentsOfURL: apiURI!)

                NSLog("API Result = %@", NSString(data: apidata!, encoding: NSUTF8StringEncoding)!)

                **if let UploadVC = self.storyboard?.instantiateViewControllerWithIdentifier("UploadMain") as? UploadMain {
                    UploadVC.ISBNstring = self.detectionString!
                }**

                break
            }

        }
    }

    print(detectionString)
    self.navigationController?.popViewControllerAnimated(true)

}



func alert(Code: String){
    let actionSheet:UIAlertController = UIAlertController(title: "Barcode", message: "\(Code)", preferredStyle: UIAlertControllerStyle.Alert)

    // for alert add .Alert instead of .Action Sheet
    // start copy
    let firstAlertAction:UIAlertAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler:
        {
            (alertAction:UIAlertAction!) in

            // action when pressed
            self.session.startRunning()
    })


    actionSheet.addAction(firstAlertAction)

}

}

最佳答案

ScanView中,您正在创建UploadMain的新实例,该实例在窗口层次结构中不可用,因此UploadMain无法使用数据。为了解决您的问题,您需要创建一个protocol并将该协议的委托传递给ScanView。因此,像这样创建一个protocol

protocol IsbnDelegate {
    func passData(isbnStr: String)
}

现在,在UploadMain中继承此协议,并在passData中覆盖其方法UploadMain,如下所示
class UploadMain: UIViewController,UITextFieldDelegate,IsbnDelegate  {

     //your code

     //Add this method
     func passData(isbnStr: String) {
          self.ISBN.text = isbnStr
     }

     //Also override prepareForSegue like this

     override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
          let destVC = segue.destinationViewController as! ScanView
          destVC.delegate = self
     }
}

之后,在delegate中创建一个ScanView对象,像这样更改ScanView的代码
import UIKit
import AVFoundation
import Foundation


class ScanView : UIViewController, AVCaptureMetadataOutputObjectsDelegate {



let session         : AVCaptureSession = AVCaptureSession()
var previewLayer    : AVCaptureVideoPreviewLayer!
var detectionString : String!
let apiKey : String = "---------dddddd"
var delegate: IsbnDelegate?

override func viewDidLoad() {
    super.viewDidLoad()

    // For the sake of discussion this is the camera
    let device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)

    // Create a nilable NSError to hand off to the next method.
    // Make sure to use the "var" keyword and not "let"
    var error : NSError? = nil
    var input: AVCaptureDeviceInput = AVCaptureDeviceInput()
    do {
        input = try  AVCaptureDeviceInput(device: device) as AVCaptureDeviceInput
    } catch let myJSONError {
        print(myJSONError)
    }

    // If our input is not nil then add it to the session, otherwise we're kind of done!
    if input !=  AVCaptureDeviceInput() {
        session.addInput(input)
    }
    else {
        // This is fine for a demo, do something real with this in your app. :)
        print(error)
    }

    let output = AVCaptureMetadataOutput()
    output.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue())
    session.addOutput(output)
    output.metadataObjectTypes = output.availableMetadataObjectTypes


    previewLayer = AVCaptureVideoPreviewLayer(session: session)
    previewLayer.frame = self.view.bounds
    previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
    self.view.layer.addSublayer(previewLayer)

    // Start the scanner. You'll have to end it yourself later.
    session.startRunning()

}



// This is called when we find a known barcode type with the camera.
func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!) {

    var highlightViewRect = CGRectZero
    var barCodeObject : AVMetadataObject!
    let barCodeTypes = [AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code]


    // The scanner is capable of capturing multiple 2-dimensional barcodes in one scan.
    for metadata in metadataObjects {

        for barcodeType in barCodeTypes {

            if metadata.type == barcodeType {
                barCodeObject = self.previewLayer.transformedMetadataObjectForMetadataObject(metadata as! AVMetadataMachineReadableCodeObject)

                highlightViewRect = barCodeObject.bounds

                detectionString = (metadata as! AVMetadataMachineReadableCodeObject).stringValue

                self.session.stopRunning()

                self.alert(detectionString)

                // Daum Book API 호출
                let apiURI = NSURL(string: "https://apis.daum.net/search/book?apikey=\(apiKey)&q=\(detectionString)&searchType=isbn&output=json")

                let apidata : NSData? = NSData(contentsOfURL: apiURI!)

                NSLog("API Result = %@", NSString(data: apidata!, encoding: NSUTF8StringEncoding)!)


                //Here We are passing the data of your ScanView to UploadMain
                self.delegate.passData(self.detectionString!)

                break
            }

        }
    }

    print(detectionString)
    self.navigationController?.popViewControllerAnimated(true)

}



func alert(Code: String){
    let actionSheet:UIAlertController = UIAlertController(title: "Barcode", message: "\(Code)", preferredStyle: UIAlertControllerStyle.Alert)

    // for alert add .Alert instead of .Action Sheet
    // start copy
    let firstAlertAction:UIAlertAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler:
        {
            (alertAction:UIAlertAction!) in

            // action when pressed
            self.session.startRunning()
    })


    actionSheet.addAction(firstAlertAction)

}

}

有关protcol的更多详细信息,请点击此链接

1)Apple Documentation
2)Tutorial 1
3)Tutorial 2

希望这会帮助你。

关于ios - 快速弹出 View Controller 后如何传递数据,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38258807/

10-14 20:16