UITableViewWrapperView和UITableView大小因自动布局而异

时间:2014-12-27 20:46:04

标签: ios uitableview swift

我正在建立聊天。一切似乎都很好,但我遇到了一些'越野车'问题

我有UIViewController和UITextView栏来输入消息和UITableView。 他们处于这种约束:"V:|-(64)-[chatTable][sendMessageBar]-(keyboard)-|"。 键盘未输出时 - 此约束的常量为0。键盘输出后 - 我将常量增加到键盘高度。

当键盘未关闭时:

self.table.contentSize = (375.0,78.5)
self.table.bounds = (0.0,-490.0,375.0,568.5)
self.table.frame = (0.0,64.0,375.0,568.5)
self.table.subviews[0].frame (UITableViewWrapperView) = (0.0,0.0,375.0,568.5)
self.table.subviews[0].frame (UITableViewWrapperView) = (0.0,0.0,375.0,568.5)

当键盘出现时:

self.table.contentSize = (375.0,78.5)
self.table.bounds = (0.0,-274.0,375.0,352.5
self.table.frame = (0.0,64.0,375.0,352.5)
self.table.subviews[0].frame (UITableViewWrapperView) = (0.0,-137.5,375.0,137.5)
self.table.subviews[0].frame (UITableViewWrapperView) = (0.0,0.0,375.0,137.5)

因此,在我增加约束常量之后,UITableViewWrapperView的大小与它的superview - UITableView不同。有没有办法来解决这个问题 ?我会假设UITableViewWrapperView会根据UITableView更改其框架和边界,但事实并非如此。

任何想法是什么问题或我如何解决它?

中加入:

经过一些更多的研究 - 它似乎发生在viewWillLayoutSubviewsviewDidLayoutSubviews之间。这有点奇怪:

override func viewWillLayoutSubviews() {
    println("WrapperView Frame :991: \(self.table.subviews[0].frame)") \\ WrapperView Frame :991: (0.0,0.0,375.0,568.5)
    super.viewWillLayoutSubviews()
    println("WrapperView Frame :992: \(self.table.subviews[0].frame)") \\ WrapperView Frame :992: (0.0,0.0,375.0,568.5)
}

override func viewDidLayoutSubviews() {
    println("WrapperView Frame :6: \(self.table.subviews[0].frame)") \\ WrapperView Frame :6: (0.0,-137.5,375.0,137.5)
    super.viewDidLayoutSubviews()
    println(">> viewDidLayoutSubviews")
}

所以似乎那里发生的某些事情弄乱了UITableViewWrapperView

7 个答案:

答案 0 :(得分:35)

以下为我解决了这个问题:

func fixTableViewInsets() {
    let zContentInsets = UIEdgeInsetsZero
    tableView.contentInset = zContentInsets
    tableView.scrollIndicatorInsets = zContentInsets
}

override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()
    fixTableViewInsets()
}

我发现在viewWillAppear()中,insets都是0.但是在viewDidAppear()中,它们被修改为显然偏移了导航栏等。这使得UITableViewWrapperView与UITableView不同。 我在自己的例程中更改了insets,以便更容易尝试从不同的地方调用它。 viewWillLayoutSubviews()让它在呈现之前被更改 - 将更改放在viewDidAppear()中会导致表格加速。

答案 1 :(得分:10)

我今天遇到了这个问题,虽然@anorskdev提出的修复很好,但问题的根本原因似乎是UIViewController的automaticallyAdjustsScrollViewInsets属性,默认情况下为true。我在故事板中将其关闭,问题就消失了。在View Controller检查器中查找“调整滚动视图插入”复选框,并确保未选中它。

答案 2 :(得分:8)

似乎这是一个bug(与这个bug争夺一整天对我而言) 最后this解决方法有所帮助:

for (UIView *subview in tableView.subviews)
{
    if ([NSStringFromClass([subview class]) isEqualToString:@"UITableViewWrapperView"])
    {
        subview.frame = CGRectMake(0, 0, tableView.bounds.size.width, tableView.bounds.size.height);
    }
}

答案 3 :(得分:1)

在iOS 11中UITableViewWrapperView已经消失,因此仅在以后的iOS版本上可能会出现此问题。当我在UIViewController堆栈中推送自定义UINavigationController时,我在iOS10上遇到了它。

因此,解决方案是在自定义视图控制器中覆盖属性automaticallyAdjustsScrollViewInsets,如下所示:

override var automaticallyAdjustsScrollViewInsets: Bool {
    get {
        return false
    }
    set {

    }
}

答案 4 :(得分:1)

我在tvOS 11.3上遇到了同样的问题,除了循环遍历tableView的子视图并将 UITableViewWrapperView 的框架设置为tableView的框架外,与零插入或滚动禁用相关的任何建议都没有完成这项工作。框架。

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        for view in tableView.subviews {
            if String(describing: type(of: view)) == "UITableViewWrapperView" {
                view.frame = CGRect(x: 0, y: 0, width: tableView.bounds.size.width, height: tableView.bounds.size.height)
        }
    }
}

答案 5 :(得分:1)

经过仔细研究,我发现可以通过将safeAreaInsets上的所有layoutMarginsUITableView都设置为零来解决此问题:

快速4片段:

class CustomTableView: UITableView {

	override var safeAreaInsets: UIEdgeInsets {
		get {
			return .zero
		}
	}

	override var layoutMargins: UIEdgeInsets {
		get {
			return .zero
		}

		set {
			super.layoutMargins = .zero
		}
	}
}

主要问题是tvOS 11.0中引入的safeAreaInsets-UITableViewWrapperView仅从父视图(UITableView)中获取属性,并使用safeAreaInsets呈现内容。

答案 6 :(得分:0)

this answer给出的anorskdev的客观C版本

- (void) viewWillLayoutSubviews {
    [super viewWillLayoutSubviews];
    [tableView setContentInset:UIEdgeInsetsZero];
    [tableView setScrollIndicatorInsets:UIEdgeInsetsZero];
}

编辑:根据Steve Roythis answer中的建议,自动关闭托管ViewController上的AdjustsScrollViewInsets也是可行的,也是我所使用的,因为这样做似乎更干净禁用该行为,而不是事后予以纠正。