28

我的应用有 2 个屏幕:

  1. TableViewVC(这里没有堆栈视图)

  2. DetailVC(这里所有嵌套的堆栈视图;请参阅图片链接:嵌套堆栈视图图片)-注意,这些堆栈视图中有标签和图像。

当您按下 tableview 中的一个单元格时,它会将信息从 TableViewVC 传递到 DetailVC。问题在于在 DetailVC 中隐藏特定的 UIStackViews。我希望 DetailVC 中的各种堆栈视图中只有 2 个堆栈视图在视图加载后立即隐藏。所以我在 DetailVC 中编写了这段代码来完成这个:

override func viewDidLoad() {
    super.viewDidLoad()

    self.nameLabel.text = "John"

    self.summaryStackView.hidden = true
    self.combinedStackView.hidden = true
}

一切看起来都很棒,但 Xcode 只在运行时给出许多警告。当应用程序未运行时,Storyboard 中没有警告。请参阅链接以获取错误图片:错误图片

基本上这是很多 UISV 隐藏、UISV 间距、UISV 画布连接错误。如果我在其中隐藏相同的堆栈视图,这些错误就会消失,viewDidAppear但是应该隐藏的东西会闪现,然后它会隐藏起来。用户短暂地看到视图,然后隐藏起来,这是不好的。

很抱歉无法实际发布图片而不是链接,但仍然不能这样做。

对于如何解决这个问题,有任何的建议吗?这是针对我实际上想要发布到应用商店的应用程序 - 这是我的第一个应用程序,所以任何帮助都会很棒!

编辑/更新 1:

我找到了一个解决此代码的小方法,我将它放在名为 DetailVC 的第二个屏幕中:

// Function I use to delay hiding of views
func delay(delay: Double, closure: ()->()) {
    dispatch_after(
        dispatch_time(
            DISPATCH_TIME_NOW,
            Int64(delay * Double(NSEC_PER_SEC))
        ),
        dispatch_get_main_queue(), closure)
}

// Hide the 2 stack views after 0.0001 seconds of screen loading
override func awakeFromNib() {
    delay(0.001) { () -> () in
        self.summaryStackView.hidden = true
        self.combinedStackView.hidden = true
    }
}

// Update view screen elements after 0.1 seconds in viewWillAppear
override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)
    delay(0.1) { () -> () in
        self.nameLabel.text = "John"
    }
}

这完全摆脱了 Xcode 中关于布局约束的警告。

它仍然不完美,因为有时我会瞥见应该隐藏的视图——它们在屏幕上快速闪烁然后消失。不过这发生得太快了。

关于为什么这会消除警告的任何建议?另外,关于如何改进它以使其完美运行的任何建议???谢谢!

4

13 回答 13

87

我遇到了同样的问题,我通过将最初隐藏视图的高度限制设置为 999 的优先级来修复它。

在此处输入图像描述

问题是您的堆栈视图在您的隐藏视图上应用了 0 的高度约束,这与您的其他高度约束冲突。这是错误消息:

Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
    "<NSLayoutConstraint:0x7fa3a5004310 V:[App.DummyView:0x7fa3a5003fd0(40)]>",
    "<NSLayoutConstraint:0x7fa3a3e44190 'UISV-hiding' V:[App.DummyView:0x7fa3a5003fd0(0)]>"
)

给你的高度限制一个较低的优先级可以解决这个问题。

于 2015-12-10T09:28:10.023 回答
35

这是隐藏嵌套堆栈视图的已知问题。

这个问题基本上有3个解决方案:

  1. 将间距更改为 0,但您需要记住之前的间距值。
  2. Call innerStackView.removeFromSuperview(),但是你需要记住在哪里插入堆栈视图。
  3. 将堆栈视图包装在具有至少一个 999 约束的 UIView 中。例如顶部,领先,尾随@ 1000,底部@ 999。

第三种选择在我看来是最好的。有关此问题、发生原因、不同解决方案以及如何实施解决方案 3 的更多信息,请参阅我对类似问题的回答

于 2016-07-07T05:01:42.083 回答
8

您可以使用 UIStackView 的 removeArrangedSubview 和 removeFromSuperview 属性。

在 Objective-C 中:

 [self.topStackView removeArrangedSubview:self.summaryStackView];
 [self.summaryStackView removeFromSuperview];

 [self.topStackView removeArrangedSubview:self.combinedStackView];
 [self.combinedStackView removeFromSuperview];

来自 Apple UIStackView 文档:( https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIStackView_Class_Reference/#//apple_ref/occ/instm/UIStackView/removeArrangedSubview :)

每当视图被添加、删除或插入到排列的Subviews 数组中时,堆栈视图都会自动更新其布局。

  • removeArrangedSubview:此方法从堆栈的arrangedSubviews 数组中删除提供的视图。视图的位置和大小将不再由堆栈视图管理。但是,此方法不会从堆栈的子视图数组中删除提供的视图;因此,视图仍然显示为视图层次结构的一部分。

为了防止视图在调用堆栈的 removeArrangedSubview: 方法后出现在屏幕上,请通过调用视图的 removeFromSuperview 方法从子视图数组中显式删除视图,或者将视图的隐藏属性设置为 YES。

于 2016-02-06T11:26:24.073 回答
3

当 UIViewStack 被隐藏时,如果 UIStackView 的间距属性具有任何非零值,则由 UIStackView 自动生成的约束将引发大量 UISV-hiding、UISV-spacing、UISV-canvas-connection 警告。

这没有多大意义,它几乎可以肯定是一个框架错误。我使用的解决方法是在隐藏组件时将间距设置为零。

if hideStackView {
    myStackView.hidden = true
    myStackView.spacing = CGFloat(0)
} else {
    myStackView.hidden = false
    myStackView.spacing = CGFloat(8)
}
于 2016-05-03T09:04:40.443 回答
3

我发现如果您在✨Interface Builder✨ 中设置 hidden 属性,嵌套的 UIStackViews 会显示此行为。我的解决方案是在✨Interface Builder✨中将所有内容设置为不隐藏,并有选择地在 viewWillAppear 中隐藏内容。

于 2017-07-20T01:43:18.443 回答
1

这个错误不是关于隐藏,而是关于模棱两可的约束。您的视图中不得有任何模棱两可的约束。如果您以编程方式添加它们,您应该准确了解您添加的约束以及它们如何协同工作。如果您不以编程方式添加它们,而是使用故事板或 xib(这是一个很好的起点),请确保没有约束错误或警告。

UPD:那里的视图结构非常复杂。如果没有看到约束,很难说到底哪里出了问题。但是,我建议您逐步构建视图层次结构,并逐个添加视图并确保没有设计时/运行时警告。如果处理不当,滚动视图可能会增加另一层复杂性。了解如何在滚动视图中使用约束。无论如何,所有其他计时技巧都不是解决方案。

于 2015-11-11T03:00:06.807 回答
1

我将所有 UIStackView.hidden 代码从 viewDidLoad 移到 viewDidAppear 并且破坏约束问题消失了。就我而言,所有冲突的约束都是自动生成的,因此无法调整优先级。

我还使用此代码使其更漂亮:

UIView.animateWithDuration(0.5) {
    self.deliveryGroup.hidden = self.shipVia != "1"
}

编辑:

还需要以下代码来阻止它在设备旋转时再次发生:

override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)

    self.deliveryGroup.hidden = false

    coordinator.animateAlongsideTransition(nil) {
    context in
        self.deliveryGroup.hidden = self.shipVia != "1"
    }
}
于 2015-12-30T00:38:58.603 回答
1

我通过将隐藏命令放入 traitCollectionDidChange 来修复它。

override func traitCollectionDidChange(previousTraitCollection: UITraitCollection?) {
    super.traitCollectionDidChange(previousTraitCollection)
    self.item.hidden = true
}
于 2016-01-07T07:05:02.153 回答
1

所以,这可能只对 0.000001% 的用户有帮助,但也许这是一个限制性问题。

我最近在使用时遇到了这个问题,UICollectionViewCell我忘记检查我正在视为我的内容视图的视图的边界。当您在 IB 中创建时UITableViewCell,它会设置一个内容视图,其中默认剪辑到边界。

关键是,根据您的情况,您可以使用框架和剪辑来实现您的预​​期效果。

于 2018-11-29T20:41:31.013 回答
0

把你的隐藏命令放进去viewWillLayoutSubviews() {}

于 2015-11-11T03:20:35.150 回答
0

我通过将嵌套 UIStackView 的所有隐藏视图存储在一个数组中并将它们从超级视图和排列的子视图中删除来做到这一点。当我希望它们再次出现时,我循环遍历数组并将它们再次添加回来。这是第一步。

第二步是从父视图中删除嵌套 UIStackView 的视图后,父 UIStackView 仍然没有调整它的高度。您可以通过删除嵌套的 UIStackView 并在之后直接再次添加来解决此问题:

UIStackView *myStackView;
NSUInteger positionOfMyStackView = [parentStackView indexOfObject:myStackView];
[parentStackView removeArrangedSubview:myStackView];
[myStackView removeFromSuperview];
[parentStackView insertArrangedSubview:myStackView atIndex:positionOfMyStackView];
于 2018-07-24T17:20:40.207 回答
0

如果您在动画 HIDING 和 SHOWING 子视图时遇到问题,在动画完成中重复 .isHidden 指令可能会有所帮助。有关更多详细信息,请参见我的答案。

于 2020-08-07T22:09:28.850 回答
-3

你试过这个吗?super更改后打电话?

override func viewWillAppear() {
    self.nameLabel.text = "John"
    self.summaryStackView.hidden = true
    self.combinedStackView.hidden = true
    super.viewWillAppear()
}
于 2017-03-22T23:37:41.510 回答