2014-11-22 5 views
1

У меня есть приложение, которое позволяет сканировать QR-код для метаданных. Контроллер корневого представления имеет два текстовых поля и позволяет вам заполнить одно из этих полей сканером. Кнопка для доступа к сканеру использует «Show» segue, чтобы нажать «Сканирование» в стек навигации.Невозможно «поп» с помощью «Show» segue в XCode 6

Мое намерение состоит в том, чтобы после того, как действительное сканирование было завершено, контроллер вида передаст данные обратно родительскому контроллеру и затем будет удален.

Будучи то, что представление было нажато, я должен иметь возможность реализовать 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 

ответ

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(),^{он выполнен на основном потоке и вернул представление, как ожидалось.

Смежные вопросы