我有一个应用程序,允许您扫描QR代码的元数据。根视图控制器有两个文本字段,允许您使用扫描仪填充其中一个字段。访问扫描仪的按钮使用“显示”segue将扫描视图推送到导航堆栈。
我的意图是,一旦完成有效扫描,视图控制器就会将数据传回父控制器,然后被删除。
由于视图已被推送,我应该能够实现popViewControllerAnimated,但这不起作用。我也尝试迭代导航堆栈中的视图控制器,匹配我想要弹出的类并使用popToViewController,但我仍然坚持我试图弹出堆栈的视图。
我的viewcontroller.m
@interface ScanQRViewController ()
@end
@implementation ScanQRViewController
@synthesize scanPreview, scanPreviewLayer, scanSession, addyString, delegate;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
scanSession = nil;
[self startScanning];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark QR code scanning
-(void)startScanning {
addyString = nil;
NSError *error;
// create capture device and input
AVCaptureDevice *capDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:capDevice error:&error];
// error checking
if(!input) {
NSLog(@"%@", [error localizedDescription]);
}
// init the capture session
scanSession = [[AVCaptureSession alloc] init];
[scanSession addInput:input];
AVCaptureMetadataOutput *metaOutput = [[AVCaptureMetadataOutput alloc] init];
[scanSession addOutput:metaOutput];
// assign to dispatch queue
dispatch_queue_t dispatchQueue;
dispatchQueue = dispatch_queue_create("qrQueue", NULL);
[metaOutput setMetadataObjectsDelegate:self queue:dispatchQueue];
[metaOutput setMetadataObjectTypes:[NSArray arrayWithObject:AVMetadataObjectTypeQRCode]];
// create camera view for user
scanPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:scanSession];
[scanPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
[scanPreviewLayer setFrame:scanPreview.layer.bounds];
[scanPreview.layer addSublayer:scanPreviewLayer];
// start running sesssion
[scanSession startRunning];
}
- (void)stopScanning {
[scanSession stopRunning];
scanSession = nil;
[scanPreviewLayer removeFromSuperlayer];
}
#pragma mark AV Delegate Methods
-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection {
// check for objects
if (metadataObjects != nil && [metadataObjects count] > 0) {
//get the last object
AVMetadataMachineReadableCodeObject *metaObj = [metadataObjects objectAtIndex:0];
if([[metaObj type] isEqualToString:AVMetadataObjectTypeQRCode]) {
// remove url string if exists
if ([[[metaObj stringValue] substringToIndex:9] isEqualToString:@"zetacoin:"]) {
addyString = [[metaObj stringValue] substringFromIndex:9];
} else {
addyString = [metaObj stringValue];
}
}
[self stopScanning];
[self dismissView];
}
}
#pragma mark - Navigation
- (void)dismissView {
[delegate ScanQRCodeDidFinish:self];
[self.navigationController popViewControllerAnimated:YES];
}
@end
答案 0 :(得分:2)
所以我想出了这个问题的问题。本质上,当将数据传递回父控制器给委托时,我不在主线程上。因此它最终会超时并返回视图,但速度非常慢。我的两个观点:
QRScanner.m<扫描视图
@interface ScanQRViewController ()
@end
@implementation ScanQRViewController
@synthesize scanPreview, scanPreviewLayer, scanSession, addyString, delegate;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
scanSession = nil;
[self startScanning];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark QR code scanning
-(void)startScanning {
addyString = nil;
NSError *error;
// create capture device and input
AVCaptureDevice *capDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:capDevice error:&error];
// error checking
if(!input) {
NSLog(@"%@", [error localizedDescription]);
}
// init the capture session
scanSession = [[AVCaptureSession alloc] init];
[scanSession addInput:input];
AVCaptureMetadataOutput *metaOutput = [[AVCaptureMetadataOutput alloc] init];
[scanSession addOutput:metaOutput];
// assign to dispatch queue
dispatch_queue_t dispatchQueue;
dispatchQueue = dispatch_queue_create("qrQueue", NULL);
[metaOutput setMetadataObjectsDelegate:self queue:dispatchQueue];
[metaOutput setMetadataObjectTypes:[NSArray arrayWithObject:AVMetadataObjectTypeQRCode]];
// create camera view for user
scanPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:scanSession];
[scanPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
[scanPreviewLayer setFrame:scanPreview.layer.bounds];
[scanPreview.layer addSublayer:scanPreviewLayer];
// start running sesssion
[scanSession startRunning];
}
- (void)stopScanning {
[scanSession stopRunning];
scanSession = nil;
[scanPreviewLayer removeFromSuperlayer];
}
#pragma mark AV Delegate Methods
-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection {
// check for objects
if (metadataObjects != nil && [metadataObjects count] > 0) {
//get the last object
AVMetadataMachineReadableCodeObject *metaObj = [metadataObjects objectAtIndex:0];
if([[metaObj type] isEqualToString:AVMetadataObjectTypeQRCode]) {
// remove url string if exists
if ([[[metaObj stringValue] substringToIndex:9] isEqualToString:@"zetacoin:"]) {
addyString = [[metaObj stringValue] substringFromIndex:9];
} else {
addyString = [metaObj stringValue];
}
}
[self stopScanning];
[self dismissView];
}
}
#pragma mark - Navigation
- (void)dismissView {
NSLog(@"%@", self.navigationController);
[delegate ScanQRCodeDidFinish:self];
}
@end
AddAddress.m<我试图回到
的观点#import "AddAddressViewController.h"
#import "ScanQRViewController.h"
@interface AddAddressViewController ()
@end
@implementation AddAddressViewController
@synthesize nameField, addressField, addressText;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.navigationController.navigationItem.backBarButtonItem.title = @"Back";
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)viewWillAppear:(BOOL)animated {
// check to see if there's an address (QR) add to text field
if (addressText != nil) {
addressField.text = addressText;
NSLog(@"Address: %@", addressText); // debugging
}
}
#pragma mark delegate methods
- (void)ScanQRCodeDidFinish:(ScanQRViewController *)sqrvc {
if (![NSThread isMainThread]) {
dispatch_sync(dispatch_get_main_queue(), ^{
addressField.text = sqrvc.addyString;
[self.navigationController popViewControllerAnimated:YES];
});
} else {
addressField.text = sqrvc.addyString;
[self.navigationController popViewControllerAnimated:YES];
}
}
#pragma mark - Navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
ScanQRViewController *sqvc = [segue destinationViewController];
sqvc.delegate = self;
}
@end
通过添加dispatch_sync(dispatch_get_main_queue(),^ {它在主线程上执行并按预期返回视图。