UIView 的框架被随机覆盖

UIView's frame gets overwritten randomly

我对 UIViews 的设置方式有疑问。

情况

我有一个视图,我将向其添加一些详细视图。这些详细视图是按顺序排列的,很像 UITableView 的行。这实际上是一个很好的比较。不同之处在于,在这个视图中,我们不是上下滚动,而是横向滚动。

在这些详细视图中,屏幕上始终只有一个。当我添加第一个屏幕时,我还会加载下一个屏幕(向右)并将其绘制出屏幕(再次向右)。当用户点击一个按钮时,我们会在下一个视图之前显示一个小动画。最后一个可见视图从左侧滑出,第二个视图从右侧滑出。在那一刻,我保留对现在左侧视图的引用,并加载一个新的右侧视图(如果有的话)。我创建了一个协议,使任何其他对象成为我所谓的 SlidableDetailViewController (SDVC).

的数据源

目前,我在数据源 didSet 期间配置详细视图。在此设置期间,它会生成这三个帧(同样是左帧、中帧和右帧)。

问题

当视图加载并首次出现在屏幕上时,中心视图的框架不是应该的,而是小得多。第二个详细视图将正确显示。当我回到第一个时,框架也会更新和更正。

当我对其进行调试时,帧计算和设置正确。当我进入 viewWillAppear(_:) 时,甚至视图的框架也是我所期望的。当我在 viewDidAppear(_:) 中做同样的事情时,它已经缩小到没人想要的奇怪大小。我什么都没做;我只是用它们来调试这里的代码。

有人看到我做错了什么了吗?

我很确定这只是我的愚蠢错误,但我现在无法弄清楚。

代码示例更新

正在计算帧数:

private func calculateFrames() {
    // Get the size for our views from the dataSource.
    let detailViewSize: CGSize
    if let theDataSource = dataSource {
        detailViewSize = theDataSource.detailViewSize()
    } else {
        // Just use a few default values.
        detailViewSize = CGSizeMake(320, 185)
    }

    // Calculate the frame for on screen display.
    let detailFrameX = (view.frame.width - detailViewSize.width) / 2
    let detailFrameY = (view.frame.height / 2 - detailViewSize.height / 2)
    centerFrame = CGRectMake(detailFrameX, detailFrameY, detailViewSize.width, detailViewSize.height)

    // The other two frames are basically just offsets of the original centerFrame.
    leftFrame = centerFrame?.offsetBy(dx: (detailViewOffset * -1), dy: 0.0)
    rightFrame = centerFrame?.offsetBy(dx: detailViewOffset, dy: 0.0)
}

加载下一个视图(加载上一个视图的工作方式几乎相同):

func showNextDetailView() {
    // 1. If we're at the last item, we can't advance.
    if selectedIndex == detailsCount() - 1 {
        return
    }

    // 2. Check if there is a view on the left spot
    if leftView != nil {
        // 2.1. … if so, remove it from superView.
        leftView?.removeFromSuperview()
    }

    UIView.animateWithDuration(animationDuration, delay: 0.0, options: .CurveEaseInOut, animations: { () -> Void in
        // 3. Set the frame of the view at selectedIndex to leftFrame.
        self.centerView?.frame = self.leftFrame!
        // 4. Set the frame of the view at selectedIndex + 1 to center frame.
        self.rightView?.frame = self.centerFrame!
        }) { (finished) -> Void in
            print("animation to next detail view finished")
    }

    // 5. Increase the selectedIndex
    selectedIndex++

    // Store the new positions for quick reference.
    if let theDataSource = dataSource {
        if let newLeftView = theDataSource.detailViewAtIndex(selectedIndex - 1) {
            leftView = newLeftView
        }

        if let newCenterView = theDataSource.detailViewAtIndex(selectedIndex) {
            centerView = newCenterView
        }

        // 6. Check if we have more views left
        if detailsCount() - 1 > selectedIndex {
            // 6.1 … and if so, add a new one to the right.
            rightView = theDataSource.detailViewAtIndex(selectedIndex + 1)
            rightView?.frame = rightFrame!
            contentView.addSubview(rightView!)
        } else {
            rightView = nil
        }
    }
}

谢谢!

我能够按照 rob mayoff 的建议使用普通 UIPageViewController 解决这个问题。