引言:
2007年第一部iPhone問世後,智能手機開始了取代PC終端的腳步。
時間來到2016年。
在時代巨浪的推動下,如今,移動互聯網已然成爲了IT領域的主戰場。今天的iOS應用程序已經再不是從前那簡單、嬌小的弱女子了。手機淘寶、網易海購等原生和Html5結合的超級App層出不窮。Hybrid模式大紅大紫,卻也先天不足。
在iOS開發領域,我一直鍾愛IB。
IB的源代碼由Xml所書寫,生澀難讀,難以駕馭。
所以,IB開發幾乎都是在圖形化界面中進行的。
但這卻並未妨礙IB成爲iOS開發中最具效率的開發方式。
至於箇中原因,還是Xcode強大的GUI操作界面和IB靈活的 Runtime注入,AutoLayout簡潔的適配設置,SizeClass的iPhone/iPad兼容設置。
有時我在想,如果將IB的源代碼進化成Html5風格書寫會有什麼樣的一番風景呢。
在我眼中,以IB書寫界面爲主流的iOS開發模式,是最有可能進化成爲完美的Hybrid模式,試想一下,兼容H5的IB配合Xcode強大的IDE編輯器,會帶來一種何等愉悅的開發體驗,會產生一種何等優異的Hybrid模式。性能優異,界面動態,有序的將邏輯放在前端和後端。這纔是我心目中的Hybrid—既可以輕鬆的隨App一起打包,還擁有卓越的性能,又可以隨時對界面進行動態替換。
從iOS App 支持通過Tag標記來延遲下載IB文件可以得出 ,這在技術實現上不會有任何問題。
可是一心要控制App的性能和質量的Apple會大開綠燈嗎?
短期內應該不會,但動態界面,固定邏輯也許會成爲可能。
好了,說了這麼多,我們也應該開始今天的主題了。
第一章:常見崩潰排查
連awakeFromeNib都沒有執行,程序卻崩潰了
連viewDidLoad都沒有執行,程序還是崩潰了
這個 控件/界面 纔剛一使用,程序就已經崩潰了
只是改變一點看起來沒有任何問題的layout,程序崩潰了
合併代碼後我的IB文件突然打不開了
沒有任何報錯,沒有任何警告,程序崩潰了,IB,IB,真真是讓人又愛又恨
相信許多入行iOS開發不久,或者使用IB不久的朋友都有遇到過這樣的問題。這也是很多朋友放棄在實際項目中使用IB的原因之一。
IB彷彿是一把雙刃劍,極大的提升開發效率,有着優異視圖解耦性,卻也伴隨着難纏的故障排查。
如果就到此而止了,您還會繼續使用IB嗎?
我想絕大部分開發者會放棄它,或者只使用Xib而放棄Storyboard,尤其是站在生產第一線的朋友們。
在實際開發中我也常常遇到這樣的朋友,因爲這樣或者那樣的原因而棄用了IB,或者僅僅用IB搭建了View,卻用代碼給它設置一切。
在我們實際開發中,如果不使用IB,或者不部分使用Storyboard,在開發效率上,明顯會慢於有着AndroidStudio加成的Android player。
這讓一向自稱程序高富帥的我們情何以堪。
好了,言歸正轉。
常見崩潰點:
1、Terminating app due to uncaught exception ‘NSUnknownKeyException'
-IB控件關聯代碼錯誤
問題描述:
控件關聯對象或者事件(拉線到代碼)後,移除了代碼中的(對象或者方法)卻沒有移除控件上的引用(Referencing)。此種情況必崩。
解決方案:
如果同一IB文件控件較少:
方案,展開IB右邊工具欄,切換到 Connection Inspector(帶箭頭那個)。切換點擊控件逐一排查 Referencing,先檢查同一控件有無重複Referencing(通常情況下是更改了代碼中的關聯對象,而IB中沒有移除原有的Referencing導致),如果有重複Referencing再檢查哪一個是真正對應代碼的Referencing。如果沒有找到問題,再檢查是否所有的關聯在代碼中都有對應的存在(包括事件 和方法)。
2、reason: [<UI*** 0x15550640> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key
-IB keyPath 設置錯誤(如果沒用過keyPath參考 http://blog.csdn.net/bsn1928/article/details/51372197 )
問題描述:
控件設置了不存在的keyPath。或者不應該設置KeyPath的控件被設置了KeyPath。
此種情況必崩。
解決方案:
如果同一IB文件控件較少,使用方案1,反之使用方案2:
方案1,展開IB右邊工具欄,切換到 Identity Inspector(方框帶文檔圖標那個)。展開User Defiend Runtime Attributes,找到錯誤提示中這段代碼 [<UI*** 0x15550640> setValue:forUndefinedKey:] 的鍵,按類名逐一檢查Key Path是否爲空,然後修復之。
方案2,右鍵 IB 文件 Open As -> Source Code。Command + F搜索 KeyPath=“” 。如果未找到,找到錯誤提示中這段代碼 [<UI*** 0x15550640> setValue:forUndefinedKey:] 的鍵,按類名搜索之,逐一排查,是否設置了無法找到的KeyPath。找到後,移除此KeyPath即可修復(注:源代碼中要按鍵值對刪除,否則將無法編譯通過,至於爲什麼,玩過Html的都應該知道)。(當然你也可以寫個腳本來完成如此複雜的操作,這裏只闡述原理)
第二章:利用IBDesignable創建自定義IB控件
1、準備:Xcode 7.* +
這裏介紹一下Label控件的自定義,其它控件以此類推。
新建Swift工程IBExtension,新建 IBLabel 繼承自 UILabel。在類開始前加入
@IBDesignable
代碼如下
// 在OC中 IB_Designable
// 在OC中 IBInspectable
import UIKit
@IBDesignable
class IBLabel: UILabel {
@IBInspectable var cornerRadius:CGFloat = 0{
didSet{
layer.cornerRadius = cornerRadius
layer.masksToBounds = cornerRadius > 0
}
}
@IBInspectable var borderWidth:CGFloat = 0{
didSet{
layer.masksToBounds = cornerRadius > 0
layer.borderWidth = borderWidth
}
}
@IBInspectable var borderColor:UIColor?{
didSet{
layer.masksToBounds = borderColor != nil
layer.borderColor = borderColor?.CGColor
}
}
@IBInspectable var allowSelected:Bool = false{
didSet{
if allowSelected{
userInteractionEnabled = true
addGestureRecognizer(tap)
}
else{
isSelected = false
userInteractionEnabled = false
removeGestureRecognizer(tap)
}
}
}
@IBInspectable var hiddenBorderWhenSelected = false{
didSet{
if hiddenBorderWhenSelected {layer.borderWidth = 0}
else {layer.borderWidth = borderWidth}
}
}
@IBInspectable var isSelected:Bool = false{
didSet{
if !allowSelected{
backgroundColor = normalBackgroundColor
textColor = normalTextColor
return
}
if isSelected{
backgroundColor = selectedBackgroundColor
textColor = selectedTextColor
if hiddenBorderWhenSelected {layer.borderWidth = 0}
}
else{
backgroundColor = normalBackgroundColor
textColor = normalTextColor
if hiddenBorderWhenSelected {layer.borderWidth = borderWidth}
}
}
}
@IBInspectable var normalTextColor:UIColor?
@IBInspectable var selectedTextColor:UIColor?
@IBInspectable var normalBackgroundColor:UIColor?
@IBInspectable var selectedBackgroundColor:UIColor?
lazy var tap:UITapGestureRecognizer = {
let tapGesture = UITapGestureRecognizer()
tapGesture .addTarget(self, action: #selector(IBLabel.didSelected(_:)))
return tapGesture
}()
func didSelected(gesture:UITapGestureRecognizer) {
isSelected = !isSelected
}
}
打開IB新建Label 展開IB右邊工具欄,切換到 Identity Inspector 在 Class 類中輸入我們剛纔創建的IBLabel
然後切換到 Attributes Inspector 這時你可以看到你的自定義屬性
如果你成功了
你會感受到IB突然變得如此的強大
如果失敗了
不要着急,點擊 Editor->Automaticaly Referesh View
然後再切換回來
如果還不行
沒關係,重啓Xcode
第三章:使用Storyboard創建靜態列表,並配置動態刷新方法(下期再講解)