由一次装那啥而引发的对AutoLayout探究
事情是这样的.我下午六点左右的时候没事干,去楼下闲逛,看见我的好基友chun同学在写一个界面,大概是这样的.
这个界面看起来很简单对吧.黄色的是一个view,红色的,是一个label.下面还有一个UIImageView.
但实际上这个界面搭配上他的业务需求就麻烦了.
因为这个界面所有的内容都是活的.
也就是说,你的button,红色的label,黄色的view都有可能不存在.那么,拉约束实际上就不是很好啦了.
但是当时我并不知道,我在问chun:"感觉这页面不难啊,怎么做了这么久".然后chun同学问我觉得多久能做完?
我说:"不超过两个小时,现在没什么界面能让我两个小时做不出来".其实我当时想说:不超过半个钟头的,但是觉得那么说太装b了.就说了两个小时,事实证明,两个小时救了我.
后来我听了需求之后,顿时感觉SB了.不好做啊.
赶快谷歌一下,直到看到了stackoverflow上的这个回答.
我举个例子来说明一下他的思路.
看这张图,现在的棕色方块的有一个约束是依赖与红色方块的,那么如果红色方块这时候因为业务需求需要消失,如果我们直接hidden的话,约束依然存在,导致棕色方块并不会到上面去.
而我们直接remove掉红色方块的话,棕色方块又会因为缺少约束(因为如果你remove掉红色方块,那么中间的那个vertical constraint也会被删掉),整个布局直接乱套.
所以,stackoverflow的意思就是,既然删掉红色view会导致棕色方块缺少一个约束,那我们直接给棕色方块额外增加一个与父view之间的约束不就可以了?
这个思路是行得通的,只要把额外的那个约束的priority改成low.那么在两个约束同时存在的话iOS会选择priority高的那个(也就是与红色关联的那个约束).
我确实这么做了.但我忘记了,cell是要reuse的.我remove了其中一个view之后,直接闪退了.因为当tableview 重用了我删掉了一个view的cell之后,崩溃了.
那么,要考虑另一种不删除就能解决的方法,其实很简单.就是hidden掉我们不想要的view的同时,更改priority的值.看下面一段代码.
import UIKit class MyCustomTableViewCell: UITableViewCell { @IBOutlet weak var imageToLabel: NSLayoutConstraint! @IBOutlet weak var imageToSuperVertical: NSLayoutConstraint! @IBOutlet weak var imageToProgressVertical: NSLayoutConstraint! @IBOutlet weak var myImageView: UIImageView! @IBOutlet weak var mylabel: UILabel! @IBOutlet weak var mButton: UIButton! @IBOutlet weak var progressView: UIView! override func awakeFromNib() { super.awakeFromNib() // Initialization code } func setImageToProgress(){ mylabel.hidden = true imageToLabel.priority = 750 imageToSuperVertical.priority = 750 if imageToProgressVertical.priority != 1000 { imageToProgressVertical.priority = 1000 } } func setImageToSuper(){ mylabel.hidden = true progressView.hidden = true imageToLabel.priority = 750 imageToProgressVertical.priority = 750 if imageToSuperVertical.priority != 1000 { imageToSuperVertical.priority = 1000 } } override func setSelected(selected: Bool, animated: Bool) { super.setSelected(selected, animated: animated) // Configure the view for the selected state } }
简单来说就是我们会给一个view同时拉多个同样的vertical约束,可能一个是跟父view的vertical约束,可能是跟另一个view的vertical约束,那么我们会根据server端返回的数据来决定使用哪个约束,hidden掉哪个view.完全满足了我们的需求.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { var customCell:MyCustomTableViewCell = tableView.dequeueReusableCellWithIdentifier("customCell") as! MyCustomTableViewCell customCell.mylabel.text = "this is a test" customCell.myImageView.image = UIImage(named: "niujiao.jpg") if indexPath.row == 1{ // customCell.setImageToProgress() customCell.setImageToSuper() } return customCell }
上面的代码是我用来测试的.我们看看效果.
注意第二个cell,我设置imageView与父view的vertical constraint的priority最高,降低了本来和红色label的约束的priority.so,现在imageView选择了与父view的约束.搞定!
我看了一下时间,7:59,哈哈.装b成功.
我把代码上传到了这里:https://github.com/zangqilong198812/TestConstraint
来源:叶孤城___的简书