我正在使用 iOS 6、分页 UIScrollView 和纯自动布局。
摘要:我创建了一个滚动内容页面的视图控制器。一些视图是在情节提要中创建和配置的,另一些是通过编程方式创建和配置的。这是视图层次结构:
- Main view (storyboard)
- UIScrollView (storyboard)
- content view (programmatically)
- subviews representing pages of content (programmatically)
滚动视图的约束在 IB 中配置。以下是我在代码中为内容视图配置约束的方式:
- (void)viewDidLoad
{
// ABPageScrollerContentView is a subclass of UIView; it overrides intrinsicContentSize; the size is calculated without referencing the scroll view's dimensions
self.contentView = [[ABPageScrollerContentView alloc] init];
self.contentView.translatesAutoresizingMaskIntoConstraints = NO;
[self.pageScrollerView addSubview:self.contentView];
// configure constraints between scroll view and content view...
UIView *contentView = self.contentView;
NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(contentView);
[self.pageScrollerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[contentView]|" options:0 metrics:0 views:viewsDictionary]];
[self.pageScrollerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[contentView]|" options:0 metrics:0 views:viewsDictionary]];
// the content view's subviews are added/removed in the tilePages method (not shown); tilePages is called later in the view controller lifecycle...
}
如果用户点击一个编辑按钮,另一个视图控制器会在情节提要中使用 segue 以模态方式呈现。视图控制器关闭后,系统似乎莫名其妙地修改了内容视图的框架,即使约束没有改变。
我在以下委托方法中关闭了呈现的视图控制器:
- (void)didExitEditPageViewVC:(id)controller
{
// update currently displayed page view from data model...
// logged content view frame = (0, 0; 1020, 460)
[self dismissViewControllerAnimated:YES completion:^{
// logged content view frame = (-170, 0; 1020, 460)
}];
}
我不明白框架原点的 x 分量如何从 0 变为 -170。解除视图控制器之前和之后的约束是相同的。
这是调用dismissViewControllerAnimated:completion:方法之前的框架和约束:
(lldb) po self.contentView
$0 = 0x1ede2b40 <AEBPageScrollerContentView: 0x1ede2b40; frame = (0 0; 1020 460); layer = <CALayer: 0x1edd6f00>>
(lldb) po self.pageScrollerView.constraints
$1 = 0x1ed076c0 <__NSArrayM 0x1ed076c0>(
<NSLayoutConstraint:0x1ede2980 H:|-(0)-[AEBPageScrollerContentView:0x1ede2b40] (Names: '|':UIScrollView:0x1edd3410 )>,
<NSLayoutConstraint:0x1eded480 H:[AEBPageScrollerContentView:0x1ede2b40]-(0)-| (Names: '|':UIScrollView:0x1edd3410 )>,
<NSLayoutConstraint:0x1edecbc0 V:|-(0)-[AEBPageScrollerContentView:0x1ede2b40] (Names: '|':UIScrollView:0x1edd3410 )>,
<NSLayoutConstraint:0x1ede1040 V:[AEBPageScrollerContentView:0x1ede2b40]-(0)-| (Names: '|':UIScrollView:0x1edd3410 )>
)
这是呈现视图控制器重新出现后的框架和约束:
contentView = <AEBPageScrollerContentView: 0x1ede2b40; frame = (-170 0; 1020 460); layer = <CALayer: 0x1edd6f00>>
self.pageScrollerView.constraints =
(
"<NSLayoutConstraint:0x1ede2980 H:|-(0)-[AEBPageScrollerContentView:0x1ede2b40] (Names: '|':UIScrollView:0x1edd3410 )>",
"<NSLayoutConstraint:0x1eded480 H:[AEBPageScrollerContentView:0x1ede2b40]-(0)-| (Names: '|':UIScrollView:0x1edd3410 )>",
"<NSLayoutConstraint:0x1edecbc0 V:|-(0)-[AEBPageScrollerContentView:0x1ede2b40] (Names: '|':UIScrollView:0x1edd3410 )>",
"<NSLayoutConstraint:0x1ede1040 V:[AEBPageScrollerContentView:0x1ede2b40]-(0)-| (Names: '|':UIScrollView:0x1edd3410 )>"
)
为什么内容视图的框架发生了意外变化?为什么它与约束所规定的不匹配?
对 hasAmbiguousLayout 的延迟调用会出人意料地返回 false。不抛出异常。滚动视图甚至滚动,尽管内容视图部分在屏幕外。
没有我在哪里明确设置滚动视图的内容大小;我把它留给系统。内容视图具有固有大小(内容视图的大小似乎很好;问题在于内容视图的来源)。
滚动视图的内容偏移在关闭视图控制器之前和之后是相同的。但是,内容视图原点的 x 分量的位移与内容偏移量成正比。内容偏移量越大,模式视图控制器关闭后内容视图原点的 x 分量就越负。并且,在“零”的内容偏移量处,x 分量为零。因此,如果在查看内容的第一页时呈现模态视图控制器(当内容偏移量为“零”时),则在关闭视图控制器时内容视图的框架是正确的。内容偏移为零的情况是内容视图的框架正确反映其约束的唯一情况。
我尝试在不同的地方插入对 layoutIfNeeded 的调用,但没有结果。
有什么建议么?