UIScrollView在iOS11中不滚动

时间:2017-10-05 01:05:47

标签: objective-c uiscrollview nslayoutconstraint ios11

我在代码中创建了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

现在可视格式部分被破坏的一种蹩脚的错误。

2 个答案:

答案 0 :(得分:6)

  

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

因为这是Apple的工作。

答案 1 :(得分:5)

尝试创建所有约束而不使用 NSLayoutConstraint constraintsWithVisualFormat:

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

经过几个小时试图找出导致我的代码出现问题的约束后,我碰巧将所有对 NSLayoutConstraint constraintsWithVisualFormat:的调用替换为使用 NSLayoutConstraint“通过代码”构建约束constraintWithItem:代替;现在它的工作原理应该......

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