I have created a UIScrollView in code and it works in iOS10. I updated my Xcode today and it is no longer scrolling in iOS11 (simulator is iOS11 and does not work; physical iPad is still iOS10 and works).
User can add subviews when they want. When its the first subview, I anchor it to the left side, top and bottom of the scroll view. Then I anchor the right side of the subview to the right side of the scroll view which gives the contentSize its size and so it knows it needs to enable scrolling
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));
The contentSize does become larger then the scroll view's frame:
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}
Why does iOS11 break my code?
EDIT:
Also, I try to scroll to the right to show the new subview when it appears:
[self.scrollViewMain scrollRectToVisible:playerCardView.frame animated:YES];
And it does nothing.
SOLUTION:
I changed
[self.scrollViewMain addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[playerCardView(200)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(playerCardView)]];
To
[self.scrollViewMain addConstraint:[NSLayoutConstraint constraintWithItem:self.scrollViewMain attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:playerCardView attribute:NSLayoutAttributeLeft multiplier:1 constant:10]];
The UIScrollView now has a left and right anchor and can calculate its contentSize.
Kind of a crappy bug that the Visual Format is partially broken now.