问题描述
我正在制作一个关于书的应用.在应用程序中,我想通过获取 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
希望对您有所帮助.
这篇关于如何在快速弹出视图控制器后传递数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!