UIScrollView在iOS11中不滚动

Posted

技术标签:

【中文标题】UIScrollView在iOS11中不滚动【英文标题】:UIScrollView Not scrolling in iOS11 【发布时间】:2017-10-05 01:05:47 【问题描述】:

我在代码中创建了一个UIScrollView,它可以在 ios10 中使用。我今天更新了我的 Xcode,它在 iOS11 中不再滚动(模拟器是 iOS11 并且不工作;物理 iPad 仍然是 iOS10 并且可以工作)。

用户可以根据需要添加子视图。当它是第一个子视图时,我将它锚定到滚动视图的左侧、顶部和底部。然后我将子视图的右侧锚定到滚动视图的右侧,这为contentSize 提供了它的大小,因此它知道它需要启用滚动

UIScrollView *scrollViewMain = [UIScrollView new];
scrollViewMain.delegate = self;
scrollViewMain.backgroundColor = [UIColor greenColor];
scrollViewMain.translatesAutoresizingMaskIntoConstraints = NO;
scrollViewMain.directionalLockEnabled = YES;
self.scrollViewMain = scrollViewMain;

... // other code

if (self.countPlayers == 1) 
    [self.scrollViewMain addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[playerCardView(400)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(playerCardView)]];
    [self.scrollViewMain addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-20-[playerCardView]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(playerCardView)]];

    NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:self.scrollViewMain attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:playerCardView attribute:NSLayoutAttributeRight multiplier:1 constant:10];

    self.constraintScrollViewRight = constraint;

    [self.scrollViewMain addConstraint:constraint];

else 
    [self.scrollViewMain addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[previousPlayerCardView]-[playerCardView(==previousPlayerCardView)]" options:0 metrics:nil views:@@"previousPlayerCardView": player.previousPlayer.playerViewCard, @"playerCardView": player.playerViewCard]];

    [self.scrollViewMain addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-20-[playerCardView]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(playerCardView)]];


if (self.constraintScrollViewRight) 
    [self.scrollViewMain removeConstraint:self.constraintScrollViewRight];


NSLayoutConstraint *constraintRight = [NSLayoutConstraint constraintWithItem:self.scrollViewMain attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:playerCardView attribute:NSLayoutAttributeRight multiplier:1 constant:10];
self.constraintScrollViewRight = constraintRight;
[self.scrollViewMain addConstraint:constraintRight];

[self.scrollViewMain layoutIfNeeded];
DLog(@"self.scrollViewMain: %@", self.scrollViewMain);
DLog(@"self.scrollViewMain.contentSize: %@", NSStringFromCGSize(self.scrollViewMain.contentSize));

contentSize 确实变得比滚动视图的框架大:

2017-10-04 20:01:58.479446-0500 [ViewController addPlayer]_block_invoke [Line 242] self.scrollViewMain: <UIScrollView: 0x7fa9fd01b000; frame = (286 20; 462 1014); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x60000005ff20>; layer = <CALayer: 0x600000233580>; contentOffset: 0, 0; contentSize: 826, 89; adjustedContentInset: 0, 0, 0, 0>
2017-10-04 20:01:58.479969-0500 [ViewController addPlayer]_block_invoke [Line 243] self.scrollViewMain.contentSize: 826, 89

为什么 iOS11 会破坏我的代码?

编辑:

另外,我尝试向右滚动以在新子视图出现时显示它:

    [self.scrollViewMain scrollRectToVisible:playerCardView.frame animated:YES];

它什么也没做。

解决方案:

我变了

[self.scrollViewMain addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[playerCardView(200)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(playerCardView)]];

[self.scrollViewMain addConstraint:[NSLayoutConstraint constraintWithItem:self.scrollViewMain attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:playerCardView attribute:NSLayoutAttributeLeft multiplier:1 constant:10]];

UIScrollView 现在有一个左右锚点,可以计算它的contentSize

视觉格式现在部分损坏的一种糟糕的错误。

【问题讨论】:

有人在这方面向 Apple 提交过错误吗? 【参考方案1】:

为什么 iOS11 会破坏我的代码?

因为这是 Apple 的工作。

【讨论】:

哈哈,反应真快! :D 这是真正的男人。每次推出新的 iOS 时,都会出现问题。希望有一个切实可行的解决方案。同时,很抱歉滥用答案部分。这里有同样的问题。 同样的问题。我还有一个“无限循环”来计算content size,这会使我的应用程序在添加布局约束时冻结。 iOS 11.1 beta 上仍然存在同样的问题。 :(【参考方案2】:

尝试在不使用 NSLayoutConstraint constraintsWithVisualFormat 的情况下创建所有约束:

升级到 XCode 9 后,我在 iOS 11 上的应用也遇到了完全相同的问题。

经过几个小时试图找出是什么约束导致我的代码出现问题后,我碰巧将所有对 NSLayoutConstraint constraintsWithVisualFormat: 的调用替换为使用 NSLayoutConstraint “按代码”构建约束constraintWithItem: 代替;现在它可以正常工作了......

我猜苹果已经修改了可视格式分析器,导致一些意想不到的副作用......

【讨论】:

这是一个重要的重构......还有其他人与@Hypo 一样成功吗?还有@Hypo,你是重构all你的约束还是只是UIScrollView的子视图? 只是 UIScrollView 的直接子视图...我的猜测是,只有连接到 UIScrollView 的内容宽度和/或高度的约束才需要重构...至少是这样在我的情况下看起来像什么...... 做到了。我将 VF 更改为约束,它现在滚动。添加了解决方案。我猜它只与UIScrollView有关;子视图需要附加到滚动视图的一侧,以便它可以计算contentSize 并知道它是否需要滚动。

以上是关于UIScrollView在iOS11中不滚动的主要内容,如果未能解决你的问题,请参考以下文章

iOS开发UI篇—UIScrollView控件介绍

iOS开发UI篇—UIScrollView控件介绍

UIScrollView 在 customView 中不滚动

UIScrollView + LargeTitle (iOS 11) - 滚动到顶部并显示大标题

iOS开发UI篇—UIScrollView控件实现图片缩放功能

_adjustContentOffsetIfNecessary - UIScrollView 自动滚动到顶部