事情是這樣的.我下午六點左右的時候沒事干,去樓下閒逛,看見我的好基友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