Swift:出现了神秘的约束
Posted
技术标签:
【中文标题】Swift:出现了神秘的约束【英文标题】:Swift: Mysterious constraint appearing 【发布时间】:2017-02-13 18:50:57 【问题描述】:我正在尝试在 UICollectionView 中创建警报列表,其中“开启”警报具有图像 (alarmImg) 和时间标签 (alarmLbl),而“关闭”警报具有图像和空白时间标签。我希望“关闭”警报图像居中,而“开启”警报图像有一个偏移量以说明标签。
这是我在cellForItemAtIndexPath
中的代码,其中 cell 是一个出队的 cell,alarmLbls 是一个闹钟时间的字符串数组。
cell.alarmLbl.text = alarmLbls[indexPath.row]
if alarmLbls[indexPath.row] == ""
cell.alarmImg.image = UIImage(named: "alarm_off")
let alarmImgYConstraintOff = NSLayoutConstraint(item: cell.alarmImg, attribute: .CenterY, relatedBy: .Equal, toItem: cell.mainView, attribute: .CenterY, multiplier: 1, constant: 0)
alarmImgYConstraintOff.active = true
cell.layoutIfNeeded()
else
cell.alarmImg.image = UIImage(named: "alarm_on")
let alarmImgYConstraintOn = NSLayoutConstraint(item: cell.alarmImg, attribute: .CenterY, relatedBy: .Equal, toItem: cell.mainView, attribute: .CenterY, multiplier: 0.75, constant: 0)
alarmImgYConstraintOn.active = true
cell.layoutIfNeeded()
初始布局看起来不错,但是当我在包含“on”警报的单元格上调用 reloadItemsAtIndexPaths
时,我收到一个约束错误,指示正在应用“off”约束,在这种情况下,“on”约束中断并且图像向中心移动。不过,根据打印测试,第一个 if
块似乎没有被这些单元格调用(仅适用于从屏幕外重新加载的“关闭”单元格),这是我设置这些约束的唯一地方.
我几乎尝试了所有我能想到的解决方案迭代:
-
强制
alarmImgYConstraintOff.active = false
通过 IB 设置中心约束并以编程方式将其关闭
将“on”块切换到if
语句
将else
更改为else if
将“on”约束的优先级设置为高于“off”约束的优先级只会使所有“off”图像在重新加载时向上移动。但是,由于某种原因,在第四次重新加载时,图像会移回其原始居中(正确)位置。
关于我在这里做错了什么有什么想法吗?
编辑:关闭不需要的约束的代码
cell.alarmLbl.text = alarmLbls[indexPath.row]
let alarmImgYConstraintOff = NSLayoutConstraint(item: cell.alarmImg, attribute: .CenterY, relatedBy: .Equal, toItem: cell.mainView, attribute: .CenterY, multiplier: 1, constant: 0)
let alarmImgYConstraintOn = NSLayoutConstraint(item: cell.alarmImg, attribute: .CenterY, relatedBy: .Equal, toItem: cell.mainView, attribute: .CenterY, multiplier: 0.75, constant: 0)
if alarmLbls[indexPath.row] == ""
cell.alarmImg.image = UIImage(named: "alarm_off")
alarmImgYConstraintOn.active = false
alarmImgYConstraintOff.active = true
cell.layoutIfNeeded()
else
cell.alarmImg.image = UIImage(named: "alarm_on")
alarmImgYConstraintOff.active = false
alarmImgYConstraintOn.active = true
cell.layoutIfNeeded()
初始布局看起来不错,和以前一样,但是一旦我重新加载“打开”单元格(保存第一次重新加载),布局仍然会中断。例如。 “on”单元格的第二次重新加载中断,所有“on”和“off”单元格的后续重新加载也是如此(尽管“off”单元格没有明显差异);但是,如果我先重新加载“关闭”单元格,则在重新加载“开启”单元格之前不会有任何中断。
【问题讨论】:
当您打开一个约束时,您应该关闭另一个。如果您尝试过但它不起作用,那么您可能没有正确执行。您可以发布该尝试的代码吗? 已编辑问题以包含新代码和结果!不幸的是,仍然没有骰子。 【参考方案1】:当您设置alarmImgYConstraintOff.active = true
时,您只是在已有的基础上添加了第二个约束。在应用新约束之前先尝试删除不需要的约束。这应该可以解决问题。
【讨论】:
我已经根据您的建议发布了我的代码,但我仍然看到问题(请参阅编辑后的问题)。 我最近在我的应用程序中做了一个类似的事情,涉及移动视图。我通过更改 constraint.constant 的值而不是添加和删除约束来做到这一点,并且没有任何问题。也许试试看? 我刚刚尝试了一个约束,在“off”块中设置 .constant = 0,在“on”块中设置 -10。 “打开”单元格重新加载布局中断,但图像仍保留在应有的位置。 “关闭”单元格重新加载布局中断,将它们移动到 -10 位置。一旦我重新加载“打开”单元格,问题似乎又开始了。不过有趣的是,对于一个(但不是全部)“关闭”单元格,图像会在第四次重新加载时移回正确的位置?【参考方案2】:尝试保存对同一约束的引用并将 .multiplier 更改为 1 或 0.75,无需更改整个约束即可更改它。
【讨论】:
看起来约束乘数是只读属性,所以你不能通过将 .multiplier 设置为不同的值来修改它们。以上是关于Swift:出现了神秘的约束的主要内容,如果未能解决你的问题,请参考以下文章