【问题标题】:Unable to "pop" view controller using "Show" segue in XCode 6无法在 XCode 6 中使用“显示”segue“弹出”视图控制器
【发布时间】:2014-11-22 04:39:15
【问题描述】:

我有一个应用程序可让您扫描 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

【问题讨论】:

    标签: objective-c iphone xcode uinavigationcontroller segue


    【解决方案1】:

    所以我想出了这个问题的问题。本质上,当将数据传递回父控制器给委托时,我不在主线程上。因此,它最终会超时并返回视图,但速度非常慢。我的两个观点:

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

    【讨论】:

      猜你喜欢
      • 2017-05-13
      • 1970-01-01
      • 2014-12-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-19
      相关资源
      最近更新 更多