Search code examples
iosobjective-cuiviewtabbarcontroller

Switching tabs in tabbarcontroller giving different results when switching by gesturerecognizer swipe to just tapping tab


i have a tabbarcontroller with 2 tabs. i have set up a swipe gesturerecognizer to allow users to swipe to go between tabs and users can also just tap on a tab to go to that tab too.

in the viewcontroller of the 2nd tab i have a subview within the main view. ive set up the subview with a pan gesturerecognizer that allows users to move the subview with a 2 finger drag. the default subview position is the bottom right of the view (from storyboard). if users drag the subview to a different position, i save the centrepoint of the subview in viewwilldisappear if users swipe to the first tab or just tap the first tab on the tabbar. when users return back to the 2nd tab (via swipe from first tab view or by tapping 2nd tab on tabbar) i set the centre of the subview to the saved centrepoint property in viewWillAppear.

strangely, if i manulaly move the subview position from the bottom right (to say topleft), the following occurs on tab change

  1. if i go from tab2 to tab 1 by tapping on tabbar, then go back to tab2 by swiping left - the subview remains in the correct "moved" position ie top right

  2. but if i go from tab2 to tab 1 by swiping right, and then go back to tab2 by swiping left - the subview at first momentarily appears in the default bottom right position before disappearing and reappearing straight away in the correct ("moved") position ie top left

  3. finally, if i go to tab 1 by either method, but then go back to tab 2 by tapping the tabbar, the subview only appears in the default bottom right position (not reflecting the previous move). ive checked and the line of code in viewWillAppear in tab2 viewcontroller does appear to be running but it seems to me as though some other tabbar related code might be running afterwards to put the subview back in the default position

any ideas of what is happening and how i can get the subview new position to stick? and also how i can stop the subview momentarily appearing in the default position described in point 2 above. any help appreciated

here is my swipe to other tab code

- (IBAction)nextTab:(id)sender {

NSInteger fromIndex = [self.tabBarController selectedIndex];
NSInteger toIndex = fromIndex + 1;

if (toIndex > self.tabBarController.viewControllers.count - 1) {
    return;
} else {

    //transition code
    UIView *fromView = self.tabBarController.selectedViewController.view;//create the from view
    UIView *toView = [[self.tabBarController.viewControllers objectAtIndex:toIndex] view];//create the to view

    // Get the size of the view area.
    CGRect viewSize = fromView.frame;
    BOOL scrollRight = toIndex > fromIndex;

    // Add the to view to the tab bar view.
    [fromView.superview addSubview:toView];

    // Position it off screen.
    UIInterfaceOrientation orientation = self.interfaceOrientation;
    if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown) {
        toView.frame = CGRectMake((scrollRight ? 768 : -768), viewSize.origin.y, 768, viewSize.size.height);
    } else {
        toView.frame = CGRectMake((scrollRight ? 1024 : -1024), viewSize.origin.y, 1024, viewSize.size.height);
    }

    [UIView animateWithDuration:0.3
                     animations: ^{

                         // Animate the views on and off the screen. This will appear to slide.
                         if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown) {
                             fromView.frame =CGRectMake((scrollRight ? -768 : 768), viewSize.origin.y, 768, viewSize.size.height);
                             toView.frame =CGRectMake(0, viewSize.origin.y, 768, viewSize.size.height);
                         } else {
                             fromView.frame =CGRectMake((scrollRight ? -1024 : 1024), viewSize.origin.y, 1024, viewSize.size.height);
                             toView.frame =CGRectMake(0, viewSize.origin.y, 1024, viewSize.size.height);
                         }

// fromView.frame =CGRectMake((scrollRight ? -768 : 768), viewSize.origin.y, 768, viewSize.size.height); // toView.frame =CGRectMake(0, viewSize.origin.y, 768, viewSize.size.height); }

                     completion:^(BOOL finished) {
                         if (finished) {
                             // Remove the old view from the tabbar view.
                             [fromView removeFromSuperview];
                             self.tabBarController.selectedIndex = toIndex;
                         }
                     }];
}

}

and here is my viewwillappear code in the 2nd tab

-(void)viewWillAppear:(BOOL)animated{

[super viewWillAppear:animated];//call to super ow super will run its own code only?


//show the clock and then use ns timer to keep it updating
[self updateClock:nil];
[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(updateClock:) userInfo:nil repeats:YES];

//position the clock in custom spot if repositioned
self.clockView.center = self.clockViewCentre;
NSLog(@"x= %f",self.clockView.center.x);

}


Solution

  • viewWillAppear is called before the layout is finalized. So the code that changes the center of the clockView should be in viewDidLayoutSubviews.