Search code examples
iosuinavigationcontrollersegueuistoryboardsegue

Proper way to unwind to HomeViewController?? Unbalanced Errors


I have an app and I have been struggling with apparent bad tutorials and was tore a new one on a previous thread so kinda apprehensive to post again. Sorry I learn by doing always have always will.

Anyway My login, Registration and other functionality is working perfectly. I am just having a rough time with the Barcode scan using AVFoundation. I setup my flow to go

Barcode Scan Flow
(source: leaguelaunch.com)

Button Click on HomeViewController to Segue to BarcodeViewController after scan it pushes to the ScanResultsViewController.

ScanResultsViewController is going to send JSON post data and render the response but I have nothing in here yet due to the errors Im getting. All I have in here is this code to Unwind directly to the HomeViewController instead of having to Push Back (BarcodeView) then Back (HomeView)

- (void)viewDidLoad
{
    [super viewDidLoad];
    UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithTitle:@"Back" style:UIBarButtonItemStyleBordered target:self action:@selector(back)];
    self.navigationItem.hidesBackButton = YES;
    self.navigationItem.leftBarButtonItem = item;
    NSLog(@"Made it to Success!!!");
}

-(void)back{
    [self performSegueWithIdentifier:@"unwindToHomeResult" sender:self];
}

As you can see it will work but it could work once or it could work 10 times before I get the error.

2014-05-25 12:11:32.378 selfcheckin[3344:60b] QR Code = {"stop_id":"3","event_id":"1"}
2014-05-25 12:11:32.801 selfcheckin[3344:60b] StopReading Called
2014-05-25 12:11:32.812 selfcheckin[3344:60b] Made it to Success!!!
2014-05-25 12:11:42.615 selfcheckin[3344:60b] QR Code = {"stop_id":"3","event_id":"1"}
2014-05-25 12:11:43.322 selfcheckin[3344:60b] StopReading Called
2014-05-25 12:11:43.334 selfcheckin[3344:60b] Made it to Success!!!
2014-05-25 12:11:50.850 selfcheckin[3344:60b] QR Code = {"stop_id":"3","event_id":"1"}
2014-05-25 12:11:51.296 selfcheckin[3344:60b] StopReading Called
2014-05-25 12:11:51.308 selfcheckin[3344:60b] Made it to Success!!!
2014-05-25 12:11:51.349 selfcheckin[3344:60b] QR Code = {"stop_id":"3","event_id":"1"}
2014-05-25 12:11:51.352 selfcheckin[3344:60b] StopReading Called
2014-05-25 12:11:51.370 selfcheckin[3344:60b] nested push animation can result in corrupted navigation bar
2014-05-25 12:11:51.759 selfcheckin[3344:60b] Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted.
2014-05-25 12:11:51.851 selfcheckin[3344:60b] Unbalanced calls to begin/end appearance transitions for <ScanResultsViewController: 0x14e86570>.

So my main question is How to I get back from the ResultsView to the HomeView. Im tempted to just nix the NavigationController and see if I can do without. Any pointers on where I may be going wrong or the proper way to do this

Thx


Solution

  • It appears you are pushing two ScanResultsViewControllers onto the navigation stack at roughly the same time, which would corrupt the navigation bar and cause unwind segues to break.

    I bet the reason that that is happening is because your BarcodeViewController is scanning for barcodes/QR-codes but does not stop scanning once one is found. Make sure to stop scanning for barcodes (or set a flag at least) when you successfully find one to make sure you only push one ScanResultsViewController.

    I had this same exact problem happen to me when I implemented a QR-code scanner in one of my apps a while back. The following method would get called if a barcode/QR-code was found (I was using ZXingObjC, just FYI); you probably have a similar method in your BarcodeViewController:

    - (void)captureResult:(ZXCapture *)capture result:(ZXResult *)result
    {
        if (result) {
            [self performSegueWithIdentifier:@"ScanResults"];
        }
    }
    

    The problem here is that this method can get called again even after the call to perform the segue, which means I was sometimes performing the segue twice. To stop this, I effectively stopped this by simply remembering that I had already found a barcode with something like this:

    - (void)captureResult:(ZXCapture *)capture result:(ZXResult *)result
    {
        if (result && !self.foundBarcode) {
            self.foundBarcode = YES;
            [self performSegueWithIdentifier:@"ScanResults"];
        }
    }
    

    ... which prevented the segue from being performed twice. I imagine your scenario is probably pretty similar.