无法使用XCode 6中的“显示”segue“弹出”视图控制器

时间:2014-11-22 04:39:15

标签: objective-c iphone xcode uinavigationcontroller segue

我有一个应用程序,允许您扫描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

1 个答案:

答案 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(),^ {它在主线程上执行并按预期返回视图。