如何在swift中弹出视图控制器后传递数据

时间:2016-07-08 04:10:48

标签: ios xcode swift

我正在制作一本关于书的应用程序。 在应用程序中, 我想通过获取ISBN(条形码)

来使应用程序自动填充书籍信息

views

有2个班级。 一个是'UploadMain',另一个是'ScanView'

我可以通过扫描获得ISBN, 但我有一个问题是将数据从ScanView传递到UploadMain。

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

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)

}

}

2 个答案:

答案 0 :(得分:1)

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

希望这会对你有所帮助。

答案 1 :(得分:0)

对我而言,您似乎正在从视图控制器传递数据 back

打电话的时候 <audio>

您正在创建该视图控制器的新实例,并且它已成功接收数据(但您永远无法使用它)。

您想要做的是发送数据

我可以为你写出来,但实际上是一些很棒的教程

text
video