简单的 SwiftUI 代码产生:UIViewAlertForUnsatisfiableConstraints。为啥?

Posted

技术标签:

【中文标题】简单的 SwiftUI 代码产生:UIViewAlertForUnsatisfiableConstraints。为啥?【英文标题】:Simple SwiftUI code yields: UIViewAlertForUnsatisfiableConstraints. Why?简单的 SwiftUI 代码产生:UIViewAlertForUnsatisfiableConstraints。为什么? 【发布时间】:2021-02-10 03:23:24 【问题描述】:

环境: Xcode 版本 12.4 (12D4e)

场景:我发现了一个明显违反约束的区域。 我将其缩小到 .navigationTitle。

import SwiftUI

struct ContentView: View 
    var body: some View 
        NavigationView 
            VStack 
                Text("Hello World")
            .navigationTitle("Turkey")
        
    

就是这样。 如果我删除 .navigationTitle(),它就会清除。

以下是控制台中列出的约束违规:


2021-02-09 19:14:38.578190-0800 NavBarCheck[6300:437683] [LayoutConstraints] Unable to simultaneously satisfy constraints.
    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. 
(
    "<NSLayoutConstraint:0x600003149ef0 'BIB_Trailing_CB_Leading' H:[_UIModernBarButton:0x12c01a770]-(6)-[_UIModernBarButton:0x12c0191e0'Turkey']   (active)>",
    "<NSLayoutConstraint:0x600003149f40 'CB_Trailing_Trailing' _UIModernBarButton:0x12c0191e0'Turkey'.trailing <= _UIButtonBarButton:0x12c018560.trailing   (active)>",
    "<NSLayoutConstraint:0x60000314acb0 'UINav_static_button_horiz_position' _UIModernBarButton:0x12c01a770.leading == UILayoutGuide:0x600002b65260'UIViewLayoutMarginsGuide'.leading   (active)>",
    "<NSLayoutConstraint:0x60000314ad00 'UINavItemContentGuide-leading' H:[_UIButtonBarButton:0x12c018560]-(0)-[UILayoutGuide:0x600002b65180'UINavigationBarItemContentLayoutGuide']   (active)>",
    "<NSLayoutConstraint:0x60000314c780 'UINavItemContentGuide-trailing' UILayoutGuide:0x600002b65180'UINavigationBarItemContentLayoutGuide'.trailing == _UINavigationBarContentView:0x12ae0f100.trailing   (active)>",
    "<NSLayoutConstraint:0x60000314b3e0 'UIView-Encapsulated-Layout-Width' _UINavigationBarContentView:0x12ae0f100.width == 0   (active)>",
    "<NSLayoutConstraint:0x60000314cb40 'UIView-leftMargin-guide-constraint' H:|-(0)-[UILayoutGuide:0x600002b65260'UIViewLayoutMarginsGuide'](LTR)   (active, names: '|':_UINavigationBarContentView:0x12ae0f100 )>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x600003149ef0 'BIB_Trailing_CB_Leading' H:[_UIModernBarButton:0x12c01a770]-(6)-[_UIModernBarButton:0x12c0191e0'Turkey']   (active)>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.

问题:这是一个错误吗?或者如果不是,发生了什么并采取补救措施?

【问题讨论】:

如果你搜索“SwiftUI 约束”,这里有很多关于这个的问题。普遍的共识似乎是不关心它 【参考方案1】:

我研究这个问题很久了,这就是我的想法。我认为它会很有用:

Navigation View 的一个有趣之处在于它如何在大型设备(通常是 iPhone 和大型 iPad)上执行分屏功能。

var body: some View 
        NavigationView 
            Text("Primary")
        
    

如果你旋转到 iPhone 11 ProMax 的横向 (Cmd + ->),你会看到文本视图消失了。

SwiftUI 自动考虑横向导航视图并显示 DetailView 而不是 main(“Primary”)。

您可以通过在 NavigationView 中提供两个视图来按照 SwiftUI 期望的方式解决问题,例如:

var body: some View 
        NavigationView 
            Text("Primary")
            Text("Secondary")
        
    

由于名气不大,只能发一张带链接的照片(如果我的帖子有用,请评价): enter image description here

这就是为什么如果我们添加. navigation Bar Title(Text ("Today's Flavors"), displayMode:. inline)会抛出错误“无法同时满足约束”

因此,解决方法如下:

    向 Navigation Vi 添加第二个视图

这里,当你旋转屏幕时,屏幕#2 - Text("Secondary") 将被显示。

    var body: some View 
            NavigationView 
                Text("Primary")
                Text("Secondary")
            .navigationBarTitle(Text("Today's Flavors"), displayMode: .inline)
            
    
    修饰符.navigationViewStyle(StackNavigationViewStyle())

但是,如果您想明确指定旋转时始终显示第一个屏幕 (Text("Primary")),那么您需要添加 .navigationViewStyle(StackNavigationViewStyle) modifier()) ,它可以让您始终切换到 Text (" Primary"),无论屏幕如何。

var body: some View 
        NavigationView 
            Text("Primary")
            Text("Secondary")
        .navigationBarTitle(Text("Today's Flavors"), displayMode: .inline)
        
        .navigationViewStyle(StackNavigationViewStyle())

另外,您可以阅读有关 NavigationView 的更多信息here

【讨论】:

【参考方案2】:

ios 14.3 开始,NavigationBarTitle 和 NavigationTitle 已被弃用。尝试在 navigationView 上添加 .navigationViewStyle(StackNavigationViewStyle())

此解决方案的所有功劳归https://***.com/a/66024249/15184473

【讨论】:

在 Swift 5.5 上遇到了同样的问题,现在解决了,谢谢!

以上是关于简单的 SwiftUI 代码产生:UIViewAlertForUnsatisfiableConstraints。为啥?的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI视图状态更改使用withAnimation()方法无动画效果的解决

SwiftUI 搜索栏无法产生诊断错误

SwiftUI找回丢失的列表视图(List)动画

SwiftUI找回丢失的列表视图(List)动画

SwiftUI:设置选取器行高

SwiftUI:视图组合的代码重用