UIScrollView's origin changes after popping ba

2019-01-16 08:38发布

I have a UIViewController subclass as a scene in the storyboard that contains a UIScrollView containing various subviews. One of the subviews is a UIButton which segues into another scene UIViewController subclass. When I come back from the view (pop the UIViewController off the navigation controller stack), I find that the scroll view's origin has somehow changed, although the contentsize and contentoffset seem correct.

What's also interesting is that the app has a tab bar, and when I tab away and back to that view, the scroll view is set back correctly with offset at (0, 0).

There is basically no code involved in this process, as it's pretty much all in the storyboard. As I am fairly new to using the storyboard, I figure I'm doing something wrong, although I don't know what. Any ideas as to what that may be? Perhaps sizing issues or constraints?

16条回答
叼着烟拽天下
2楼-- · 2019-01-16 09:18

recently , I have encountered this bug, can be solved using these codes:

// fix ios 6 bug begin
- (void)viewDidDisappear:(BOOL)animated
{
    [super viewDidDisappear:animated];

    if ([[[UIDevice currentDevice] systemVersion] floatValue] < 7) {
        isRecoredforios6 = YES;
        recordedOffsetforios6 = self.tableView.contentOffset;
        recordedSizeforios6 = self.tableView.contentSize;
    }
}

- (void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];
    if (isRecoredforios6) {
        isRecoredforios6 = NO;
        self.tableView.contentSize = recordedSizeforios6;
        self.tableView.contentOffset = recordedOffsetforios6;
    }
}
// fix ios 6 bug end

thanks Peter Jacobs!

查看更多
别忘想泡老子
3楼-- · 2019-01-16 09:20

In iOS 7/8/9 simple self.automaticallyAdjustsScrollViewInsets = NO; solved the problem in my case.

查看更多
Luminary・发光体
4楼-- · 2019-01-16 09:20

None of the above worked for me, I managed to do my own custom Push/Pull animation instead and it works like a charm.

First, add this class which implements Push scenario

class PushAnimator: NSObject, UIViewControllerAnimatedTransitioning, UIViewControllerTransitioningDelegate {

func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
    return 0.5
}

func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {

    // get reference to our fromView, toView and the container view that we should perform the transition in
    let container = transitionContext.containerView
    let fromView = transitionContext.view(forKey: UITransitionContextViewKey.from)!
    let toView = transitionContext.view(forKey: UITransitionContextViewKey.to)!

    // start the toView to the right of the screen
    var frame = toView.frame
    frame.origin.x = container.frame.width
    toView.frame = frame

    // add the both views to our view controller
    container.addSubview(toView)
    container.addSubview(fromView)

    // get the duration of the animation
    let duration = self.transitionDuration(using: transitionContext)

    // perform the animation!
    UIView.animate(withDuration: duration, animations: {

        var frame = fromView.frame
        frame.origin.x = -container.frame.width
        fromView.frame = frame

        toView.frame = container.bounds

    }, completion: { _ in
        // tell our transitionContext object that we've finished animating
        transitionContext.completeTransition(true)

    })
}
}

Then add this class which implements pop scenario

import Foundation
import UIKit

class PopAnimator: NSObject, UIViewControllerAnimatedTransitioning, UIViewControllerTransitioningDelegate {

func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
    return 0.5
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
    // get reference to our fromView, toView and the container view that we should perform the transition in
    let container = transitionContext.containerView
    let fromView = transitionContext.view(forKey: UITransitionContextViewKey.from)!
    let toView = transitionContext.view(forKey: UITransitionContextViewKey.to)!

    // set up from 2D transforms that we'll use in the animation
    let offScreenRight = CGAffineTransform(translationX: container.frame.width, y: 0)

    // start the toView to the right of the screen
    var frame = toView.frame
    frame.origin.x = -container.frame.width
    toView.frame = frame

    // add the both views to our view controller
    container.addSubview(toView)
    container.addSubview(fromView)

    // get the duration of the animation
    let duration = self.transitionDuration(using: transitionContext)

    // perform the animation!
    UIView.animate(withDuration: duration, animations: {

        fromView.transform = offScreenRight
        toView.frame = container.bounds

    }, completion: { _ in
        // tell our transitionContext object that we've finished animating
        transitionContext.completeTransition(true)

    })
}
}

Then add this line to your viewDidLoad method to change default NavigationController Delegate

self.navigationController?.delegate = self

And see the magic :)

查看更多
三岁会撩人
5楼-- · 2019-01-16 09:21

Continued Issue when following the current answers:

The second attempt to open the presented view controller, without having left the presenting view controller, the problem remained. Which is why I am posting the exact steps that resulted in my solution.

  1. So, I reset the collectionView's constraints in the Storyboard, making certain they were pinned to presentingViewController's main view.

  2. Added: self.view.translatesAutoresizingMaskIntoConstraints = YES; inside the viewDidLoad of the presenting view controller.

  3. And stored, privately, the contentOffset of the collection view prior to the modally presented view controller's appearance:

    (void)viewWillDisappear:(BOOL)animated
    {
        [super viewWillDisappear:animated];
    
        self.contentOffset = self.collectionView.contentOffset;
        self.collectionView.contentOffset = CGPointZero;
    }
    
    - (void)viewDidLayoutSubviews {
         [super viewDidLayoutSubviews];
         self.collectionView.contentOffset = self.contentOffset;
    }
    
查看更多
Explosion°爆炸
6楼-- · 2019-01-16 09:25
- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];

    if ([[[UIDevice currentDevice] systemVersion] floatValue] < 7) {
        _isRecoredforios6 = YES;
        _recordedOffsetforios6 = _scrollView.contentOffset;
        _recordedSizeforios6 = _scrollView.contentSize;
        _scrollView.contentOffset = CGPointZero;
    }

}

- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];

    if (_isRecoredforios6) {
        _isRecoredforios6 = NO;
        _scrollView.contentSize = _recordedSizeforios6;
        _scrollView.contentOffset = _recordedOffsetforios6;
    }
}

I have fixed this ios6 bug , can be solved using these codes. I solved bug occurred in Scrollview. Thank above all my friends!

查看更多
该账号已被封号
7楼-- · 2019-01-16 09:27

Unfortunately, Peter and MacMark's suggestions did not work for me (Xcode 5 w/ auto-layout). The solution was to go to the storyboard, select the view controller, and Reset to Suggested Constraints in View Controller.

enter image description here

查看更多
登录 后发表回答