【问题标题】:Autolayout different in Simulator and Device模拟器和设备中的自动布局不同
【发布时间】:2018-04-13 00:43:39
【问题描述】:

我正在构建一个带有自动布局的 UITableViewCells。它在模拟器中按预期工作,没有自动布局错误或警告。

在设备(与模拟器相同的类型)上运行应用程序会显示以下日志消息,并且布局与预期不符。

2017-10-31 18:59:02.724396+0100 StaticTableTest01[8239:4373602] [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:0x170099050 V:|-(10)-[UILabel:0x100e0bb90'row 0 sec: 0']   (active, names: '|':UITableViewCellContentView:0x100e06e40 )>",
 "<NSLayoutConstraint:0x170099230 UITextField:0x100f083b0.top == UILabel:0x100e0bb90'row 0 sec: 0'.top   (active)>",
 "<NSLayoutConstraint:0x170099320 UITextField:0x100f083b0.height == 41   (active)>",
 "<NSLayoutConstraint:0x1700993c0 UITextField:0x100f083b0.bottom == UITableViewCellContentView:0x100e06e40.bottom - 10   (active)>",
 "<NSLayoutConstraint:0x174093920 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0x100e06e40.height == 43.5   (active)>"
)

造成这种差异的原因是什么?

这是 UITableViewCell 的代码

let cell = UITableViewCell()
cell.translatesAutoresizingMaskIntoConstraints = false

let lb1 = UILabel()
lb1.translatesAutoresizingMaskIntoConstraints = false
lb1.lineBreakMode = .byCharWrapping
lb1.numberOfLines = 0

if (indexPath.section == 1 && indexPath.row == 0)
{ lb1.text = "r\(indexPath.row)c:\(indexPath.section) very long text very long text very long text very long text very long text very long text very long text very long text very long text"
} else
{ lb1.text = "row \(indexPath.row) sec: \(indexPath.section)"
}


let tf1 = UITextField()
tf1.font = UIFont.boldSystemFont(ofSize: 30)
tf1.translatesAutoresizingMaskIntoConstraints = false

cell.contentView.addSubview(lb1)
cell.contentView.addSubview(tf1)

let second = lb1.superview

NSLayoutConstraint(item: lb1, attribute: .leading, relatedBy: .equal, toItem: second, attribute: .leading, multiplier: 1, constant: 10).isActive = true
NSLayoutConstraint(item: lb1, attribute: .top, relatedBy: .equal, toItem: second, attribute: .top, multiplier: 1, constant: 10).isActive = true
NSLayoutConstraint(item: lb1, attribute: .width, relatedBy: .equal, toItem:nil , attribute: .notAnAttribute , multiplier: 1, constant: 250).isActive = true

tf1.leadingAnchor.constraint(equalTo: lb1.trailingAnchor, constant: 10).isActive = true
tf1.trailingAnchor.constraint(equalTo: (second?.trailingAnchor)!, constant: -10).isActive = true
tf1.topAnchor.constraint(equalTo: lb1.topAnchor, constant: 0).isActive = true

let labelHeight = lb1.textRect(forBounds: CGRect(x:0, y:0, width:250, height:1000), limitedToNumberOfLines: 4).size.height
let textFieldHeight = tf1.intrinsicContentSize.height

tf1.heightAnchor.constraint(equalToConstant: textfHeight).isActive = true

if labelHeight >= textfHeight
{ NSLayoutConstraint(item: lb1, attribute: .bottom, relatedBy: .equal, toItem: second, attribute: .bottom, multiplier: 1, constant: -10).isActive = true
} else
{ NSLayoutConstraint(item: tf1, attribute: .bottom, relatedBy: .equal, toItem: second, attribute: .bottom, multiplier: 1, constant: -10).isActive = true
}

【问题讨论】:

  • 你的代码没有意义。在现实生活中,你永远不会说let cell = UITableViewCell()。如果您在与 UITableView 相关的情况下执行此操作,则说明您使用的表格视图不正确。如果您在任何表格视图之外执行此操作,那么您就无法使用表格视图单元格。你需要更多地思考(并解释)你真正想做的事情。你的整个界面架构都有问题;自动布局问题只是对更大问题的诊断。
  • 您应该使用tableView.dequeueReusableCell(withIdentifier:, for:))重复使用您的单元格
  • @mica - 您想动态创建静态单元格吗?这是相当混乱的。您“通过代码创建”的任何东西,几乎按照定义,不是静态的。您的图像显示 4 个单元格,它们看起来都一样(除了第 0 行第 1 部分有多行)。你还有其他细胞吗?还是有其他元素的细胞?并且您正在使用文本字段,因为它们是可编辑的?
  • @mica - 您确定您使用的模拟器配置与您的实际设备相同吗?我在 iPhone 7+ 模拟器 设备上遇到了同样的约束失败,但我在 iPhone 7 上没有得到它。无论如何,看看我的答案。未来的提示......如果您正在寻求帮助,请发布您的实际代码 - 或者至少是演示问题的实际示例。您发布的代码不会按原样运行(textfHeight 未解决),并且您不会显示颜色设置或 textField 文本。所以我们必须做一些猜测来尝试和帮助。
  • “tableView.dequeueReusableCell 不是为 IB 设计的单元格制作的吗?”不,该方法是为了内存管理目的而设计的,以便在单元格从屏幕上出现/消失时智能地重用它们,无论它们是用代码还是 IB 设计的。

标签: ios swift uitableview autolayout ios-simulator


【解决方案1】:

删除您在文本字段中设置高度约束的行:

let labelHeight = lb1.textRect(forBounds: CGRect(x:0, y:0, width:250, height:1000), limitedToNumberOfLines: 4).size.height
let textFieldHeight = tf1.intrinsicContentSize.height

// delete this line
//tf1.heightAnchor.constraint(equalToConstant: textFieldHeight).isActive = true

if labelHeight >= textFieldHeight
{ NSLayoutConstraint(item: lb1, attribute: .bottom, relatedBy: .equal, toItem: second, attribute: .bottom, multiplier: 1, constant: -10).isActive = true
} else
{ NSLayoutConstraint(item: tf1, attribute: .bottom, relatedBy: .equal, toItem: second, attribute: .bottom, multiplier: 1, constant: -10).isActive = true
}

由于您要求.intrinsicContentSize.height,因此尝试设置高度没有多大意义。

【讨论】:

  • 谢谢。对,不需要 tf1.height 约束。删除后它仍然可以在模拟器中运行,而不是在设备上。我也没有在 7+ 模拟器上得到约束错误。 - 嗯!
  • 构建tableview 我已经将estimatedRowHeight 设置为UITableViewAutomaticDimension。将其更改为 100 后,模拟器和设备的行为相似,除了在设备上,表格从屏幕的最顶部开始(用运营商、信号、电池等覆盖“状态”行),请参见屏幕截图问题 tableView?.backgroundColor = UIColor.green
  • 我认为是因为模拟器运行iOS11和设备iOS10
  • "... UITableViewAutomaticDimension。将其更改为 100 ...""iOS 11 / iOS 10" - 这是我在 cmets 中对您的问题的意思是:如果您只显示您 认为 重要的代码部分,那么我们很可能会遗漏 的部分 重要。看到这个:stackoverflow.com/help/mcve
  • 你是对的。有时很难在最小和完整之间找到正确的平衡;-) 感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-30
  • 1970-01-01
  • 2020-04-26
  • 2012-04-20
相关资源
最近更新 更多