問(wèn)題
新項(xiàng)目中自定義tabbar,重新設(shè)置了UITabbarButton的frame拇惋,當(dāng)在控制器中對(duì)title賦值時(shí)周偎,奇跡出現(xiàn):tabbar的按鈕位置會(huì)左右交換。
思考
位置的改變?cè)从谧远xtabbar撑帖,問(wèn)題代碼
override func layoutSubviews() {
...
for barButton in subviews
...
}
再看看subviews的定義
The receiver’s immediate subviews.
You can use this property to retrieve the subviews associated with your custom view hierarchies. The order of the subviews in the array reflects their visible order on the screen, with the view at index 0 being the back-most view.
For complex views declared in UIKit and other system frameworks, any subviews of the view are generally considered private and subject to change at any time. Therefore, you should not attempt to retrieve or modify subviews for these types of system-supplied views. If you do, your code may break during a future system update.
subviews的順序取決于它們?cè)谄聊簧系目梢婍樞蛉乜玻饕?的在最后,并且順序隨時(shí)可能改變胡嘿。
什么操作導(dǎo)致的等舔?
當(dāng)設(shè)置控制器的title時(shí)毅待,會(huì)產(chǎn)生bug。
再看看title的定義
A localized string that represents the view this controller manages.
Set the title to a human-readable string that describes the view. If the view controller has a valid navigation item or tab-bar item, assigning a value to this property updates the title text of those objects.
表示控制器管理的視圖的字符串。如果控制器有一個(gè)有效的navigationItem或者tabbarItem,將會(huì)更新這些對(duì)象屬性的title雏赦。
也就是會(huì)對(duì)navigationItem.title和tabBarItem.title賦值枝誊,從而引起subviews視圖順序產(chǎn)生變化宝恶。然后系統(tǒng)會(huì)調(diào)用layoutSubviews烙丛。
這時(shí)候subviews順序已經(jīng)改變,再次布局就會(huì)導(dǎo)致按鈕位置的錯(cuò)誤面氓。
驗(yàn)證
符號(hào)斷點(diǎn)subviews和layoutSubviews兵钮,查看調(diào)用棧
UIViewController設(shè)置title后蛆橡,調(diào)用了subviews,然后調(diào)用layoutSubviews掘譬。
解決
最終還是順序的問(wèn)題泰演,那就以改變前的子視圖的x值對(duì)subviews進(jìn)行排序。
排序后再去布局屁药,相對(duì)于原來(lái)UITabbarButton的順序不變粥血,也就不會(huì)產(chǎn)生左右交換。
let sortedSubviews = subviews.sorted { (view0, view1) -> Bool in
return view0.xValue < view1.xValue
}
for barButton in sortedSubviews
其他
self.navigationItem.title //sets navigation bar title.
self.tabBarItem.title // sets tab bar title.
self.title // sets both of these.