如何在快速弹出视图控制器后传递数据 [英] how to pass data after pop view controller in swift

查看:18
本文介绍了如何在快速弹出视图控制器后传递数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在制作一个关于书的应用.在应用程序中,我想通过获取 ISBN(Barcode) 使应用程序自动填充图书信息

I am making an app about book. In the app, i want to make the app auto-filling book info by getting ISBN(Barcode)

视图

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

There is 2 classes. one is 'UploadMain',the other is 'ScanView'

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

I can get ISBN by scanning, but i have a problem to pass data from ScanView to UploadMain.

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

In ScanView i have used optional Binding like below

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
}

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

i don't know whats the problem my code.

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.

In the ScanView you are creating the new instance of UploadMain, that is not available in window hierarchy, So that data is not available to the UploadMain. To solve your problem you need to create one protocol and pass the delegate of that protocol to ScanView. So create one protocol like this.

protocol IsbnDelegate {
    func passData(isbnStr: String)
}

现在在 UploadMain 中继承这个协议并在 UploadMain 中重写它的方法 passData 如下

Now inherit this protocol in UploadMain and override its method passData in the UploadMain like below

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
     }
}

然后在ScanView中创建一个delegate对象,像这样更改ScanView的代码

After that create one delegate object in ScanView, Change your code of ScanView like this

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)

}

}

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

For more detail about protcol follow this link

1) Apple 文档
2) 教程 1
3) 教程 2

希望对您有所帮助.

这篇关于如何在快速弹出视图控制器后传递数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆