UIScrollView与自动布局错误的偏移量

我有一个相当简单的视图configuration:

一个UIViewController ,在这个UIScrollView有一个子UIScrollView和一个UIImageView 。 我设置了UIImageView的高度足以突破可见区域(即高于1024pt ),并将Bottom space to superview设置为我的UIImageView 1024pt约束为固定的正值(例如20 )。

项目布局

整个设置按预期工作,图像在其父项中很好地滚动。 除了滚动视图(如果滚动到视图的底部,效果更明显),然后消失,再次出现(切换到另一个视图并返回)滚动值将被恢复,但滚动的内容滚动视图移动到其父视图的外部顶部。

这不是简单的解释,我会试图画出来: 上一段的视觉表现

如果你想testing/查看来源(或故事板,我没有编辑一行代码)。 我在我的github上放了一个小样本: https : //github.com/guillaume-algis/iOSAutoLayoutScrollView

我没有阅读iOS 6 changelog和关于这个特定主题的解释,并认为这是第二个选项(纯自动布局)的正确实现,但在这种情况下,为什么UIScrollView行为如此不正常? 我错过了什么吗?

编辑 :这是完全相同的问题#12580434 uiscrollview-autolayout问题 。 答案只是解决方法,任何人find一个正确的方法来解决这个问题,或者这是一个iOS的错误?

编辑2 :我发现另一个解决方法,保持滚动位置在相同的状态,用户离开它(这是一个改进超过12580434的接受答案):

 @interface GAViewController () @property CGPoint tempContentOffset; @end @implementation GAViewController -(void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; self.tempContentOffset = self.mainScrollView.contentOffset; self.scrollView.contentOffset = CGPointZero; } -(void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; self.scrollView.contentOffset = self.tempContentOffset; } 

这基本上保存viewWillAppear的偏移量,将其重置为原点,然后恢复viewDidAppear的值。 问题似乎发生在这两个电话之间,但是我找不到它的起源。

是的,在纯自动布局环境下,UIScrollView发生了一些奇怪的事情。 重读第二十次的iOS SDK 6.0发行说明 ,我发现:

请注意,您可以通过在视图和滚动视图的子树之外的视图(如滚动视图的超级视图)之间创build约束来使滚动视图的子视图浮动(不滚动)其他滚动内容。

将你的子视图连接到外部视图。 换句话说,就是embeddedscrollview的视图。

由于IB不允许我们在imageView和滚动视图的子树之外的视图(例如滚动视图的超级视图)之间设置约束,我已经在代码中完成了它。

 - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. [self.view removeConstraints:[self.view constraints]]; [self.scrollView removeConstraints:[self.scrollView constraints]]; [self.imageView removeConstraints:[self.imageView constraints]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|[_scrollView]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_scrollView)]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_scrollView]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_scrollView)]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|[_imageView(700)]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_imageView)]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_imageView(1500)]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_imageView)]]; } 

和vau! 有用!

编辑没有为我工作。 但是这工作:

 -(void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; self.tempContentOffset = self.scrollView.contentOffset; self.scrollView.contentOffset = CGPointZero; } - (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; self.scrollView.contentOffset = self.tempContentOffset; } 

对我来说,我去了IB点击我的视图控制器,其中包含滚动视图。 然后我去了属性检查器 – >视图控制器 – >扩展边缘 – >取消选中“顶部酒吧”和“底部酒吧”。

find简单的解决scheme,只要放

 [self setAutomaticallyAdjustsScrollViewInsets:NO]; 

在你的ViewControllers的viewDidLoad方法中

 - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view from its nib. [self setAutomaticallyAdjustsScrollViewInsets:NO]; } 

我有一个类似的问题,在UIViewController中使用一个UIScrollView,在Storyboard中不可见的顶部额外空间。 对我来说,解决scheme是取消选中ViewController storyboard属性中的“Adjust Scroll View Insets”: 在运行时查看Scroll View中的额外空间(插入)

添加全局属性contentOffset,并将当前的contentOffset保存在viewDidDisappear中。 一旦你返回方法viewDidLayoutSubviews将被调用,你可以设置你的原始contentOffset。

 - (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; [self.scrollView setContentOffset:self.contentOffset animated:FALSE]; } - (void)viewDidDisappear:(BOOL)animated { [super viewDidDisappear:animated]; self.contentOffset = self.scrollView.contentOffset; [self.scrollView setContentOffset:CGPointMake(0, 0) animated:FALSE]; } 

看起来像在viewWillAppear:期间dispatch_async解决的问题viewWillAppear:

 - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; CGPoint originalContentOffset = self.scrollView.contentOffset; self.scrollView.contentOffset = CGPointZero; dispatch_async(dispatch_get_main_queue(), ^{ self.scrollView.contentOffset = originalContentOffset; }); }