I am following the tutorial given here with some of my own modification to create a Container View Controller that should hold three different View Controllers.
But when I run the app the views are not getting swapped properly and also crashes. Here is the log report:
2015-08-05 15:25:27.564 VUTEk Go[5589:327605] -[RightViewController shouldPerformSegueWithIdentifier:sender:]
2015-08-05 15:25:27.565 VUTEk Go[5589:327605] -[RightViewController prepareForSegue:sender:]
2015-08-05 15:25:27.566 VUTEk Go[5589:327605] -[LogContainerViewController prepareForSegue:sender:]
2015-08-05 15:25:29.339 VUTEk Go[5589:327605] TAB2
2015-08-05 15:25:29.340 VUTEk Go[5589:327605] -[LogContainerViewController swapViewControllers:]
2015-08-05 15:25:29.341 VUTEk Go[5589:327605] -[LogContainerViewController prepareForSegue:sender:]
2015-08-05 15:25:29.341 VUTEk Go[5589:327605] -[LogContainerViewController swapFromViewController:toViewController:]
2015-08-05 15:25:31.363 VUTEk Go[5589:327605] TAB3
2015-08-05 15:25:31.363 VUTEk Go[5589:327605] -[LogContainerViewController swapViewControllers:]
2015-08-05 15:25:31.363 VUTEk Go[5589:327605] -[LogContainerViewController swapFromViewController:toViewController:]
2015-08-05 15:25:31.407 VUTEk Go[5589:327605] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Children view controllers (null) and <StatusLogViewController: 0x7fcbac90ca30> must have a common parent view controller when calling -[UIViewController transitionFromViewController:toViewController:duration:options:animations:completion:]'
Here is my interface file:LogContainerViewController.h
#import <UIKit/UIKit.h>
@interface LogContainerViewController : UIViewController
- (void)swapViewControllers:(int) index;
@end
And my implementation file:LogContainerViewController.m
#import "LogContainerViewController.h"
#import "ErrorLogViewController.h"
#import "WarningLogViewController.h"
#import "StatusLogViewController.h"
#define SegueIdentifierFirst @"errorSegue"
#define SegueIdentifierSecond @"warningSegue"
#define SegueIdentifierThird @"statusSegue"
@interface LogContainerViewController ()
@property (strong, nonatomic) NSString *currentSegueIdentifier;
@property (strong, nonatomic) ErrorLogViewController* errorViewController;
@property (strong, nonatomic) WarningLogViewController* warningViewController;
@property (strong, nonatomic) StatusLogViewController* statusViewController;
@property (assign, nonatomic) BOOL transitionInProgress;
@end
@implementation LogContainerViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.transitionInProgress = NO;
self.currentSegueIdentifier = SegueIdentifierFirst;
[self performSegueWithIdentifier:self.currentSegueIdentifier sender:nil];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSLog(@"%s", __PRETTY_FUNCTION__);
// Instead of creating new VCs on each seque we want to hang on to existing
// instances if we have it. Remove the second condition of the following
// two if statements to get new VC instances instead.
if ([segue.identifier isEqualToString:SegueIdentifierFirst]) {
self.errorViewController = segue.destinationViewController;
}
if ([segue.identifier isEqualToString:SegueIdentifierSecond]) {
self.warningViewController = segue.destinationViewController;
}
if ([segue.identifier isEqualToString:SegueIdentifierThird]) {
self.statusViewController = segue.destinationViewController;
}
// If we're going to the first view controller.
if ([segue.identifier isEqualToString:SegueIdentifierFirst]) {
// If this is not the first time we're loading this.
if (self.childViewControllers.count > 0) {
[self swapFromViewController:[self.childViewControllers objectAtIndex:0] toViewController:self.errorViewController];
}
else {
// If this is the very first time we're loading this we need to do
// an initial load and not a swap.
[self addChildViewController:segue.destinationViewController];
UIView* destView = ((UIViewController *)segue.destinationViewController).view;
destView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
destView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
[self.view addSubview:destView];
[segue.destinationViewController didMoveToParentViewController:self];
}
}
// By definition the second view controller will always be swapped with the
// first one.
else if ([segue.identifier isEqualToString:SegueIdentifierSecond]) {
[self swapFromViewController:[self.childViewControllers objectAtIndex:0] toViewController:self.warningViewController];
}
else if ([segue.identifier isEqualToString:SegueIdentifierThird]) {
[self swapFromViewController:[self.childViewControllers objectAtIndex:0] toViewController:self.statusViewController];
}
}
- (void)swapFromViewController:(UIViewController *)fromViewController toViewController:(UIViewController *)toViewController
{
NSLog(@"%s", __PRETTY_FUNCTION__);
toViewController.view.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
[fromViewController willMoveToParentViewController:nil];
[self addChildViewController:toViewController];
[self transitionFromViewController:fromViewController toViewController:toViewController duration:1.0 options:UIViewAnimationOptionTransitionCrossDissolve animations:nil completion:^(BOOL finished) {
[fromViewController removeFromParentViewController];
[toViewController didMoveToParentViewController:self];
self.transitionInProgress = NO;
}];
}
- (void)swapViewControllers:(int) index
{
NSLog(@"%s", __PRETTY_FUNCTION__);
if (self.transitionInProgress) {
return;
}
self.transitionInProgress = YES;
//self.currentSegueIdentifier = ([self.currentSegueIdentifier isEqualToString:SegueIdentifierFirst]) ? SegueIdentifierSecond : SegueIdentifierFirst;
if([self.currentSegueIdentifier isEqualToString:SegueIdentifierFirst] && index==0){
self.currentSegueIdentifier = SegueIdentifierFirst;
}else if ([self.currentSegueIdentifier isEqualToString:SegueIdentifierSecond] && index==1){
self.currentSegueIdentifier = SegueIdentifierSecond;
}
else{
self.currentSegueIdentifier = SegueIdentifierThird;
}
if (([self.currentSegueIdentifier isEqualToString:SegueIdentifierFirst]) && self.errorViewController && index==0) {
[self swapFromViewController:self.warningViewController toViewController:self.errorViewController];
return;
}
if (([self.currentSegueIdentifier isEqualToString:SegueIdentifierThird]) && self.statusViewController && index==2) {
[self swapFromViewController:self.warningViewController toViewController:self.statusViewController];
return;
}
if (([self.currentSegueIdentifier isEqualToString:SegueIdentifierSecond]) && self.warningViewController && index==1) {
[self swapFromViewController:self.errorViewController toViewController:self.warningViewController];
return;
}
if (([self.currentSegueIdentifier isEqualToString:SegueIdentifierThird]) && self.statusViewController && index==2) {
[self swapFromViewController:self.errorViewController toViewController:self.statusViewController];
return;
}
if (([self.currentSegueIdentifier isEqualToString:SegueIdentifierFirst]) && self.errorViewController && index==0) {
[self swapFromViewController:self.warningViewController toViewController:self.errorViewController];
return;
}
if (([self.currentSegueIdentifier isEqualToString:SegueIdentifierSecond]) && self.errorViewController && index==1) {
[self swapFromViewController:self.statusViewController toViewController:self.warningViewController];
return;
}
[self performSegueWithIdentifier:self.currentSegueIdentifier sender:nil];
}
@end
I want to load these view when I select a segment in my UISegmented View. The action for that is :
- (IBAction)printerLogSegmentChanged:(id)sender {
UISegmentedControl *s = (UISegmentedControl *)sender;
if (s.selectedSegmentIndex == 0)
{
NSLog(@"TAB1");
[self.containerViewController swapViewControllers:0];
}
else if (s.selectedSegmentIndex == 1){
NSLog(@"TAB2");
[self.containerViewController swapViewControllers:1];
}
else if (s.selectedSegmentIndex == 2){
NSLog(@"TAB3");
[self.containerViewController swapViewControllers:2];
}
else{
NSLog(@"TAB NOT Working");
}
}
But I think there is something wrong with logic of - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender; that I am using.
Any help will really be appreciated as I have been stuck on this for more than two hours and all similar question couldn't help me.
I am sharing a screen shot of my app
As you can see in the above screenshot that it swaps the wrong child view and sometime also crashes.
Thanks in advance!
via Chebli Mohamed
Aucun commentaire:
Enregistrer un commentaire