前言
其實這篇文章的重點并不在于runtime霉祸,只是我選擇了用runtime擴展,而不是繼承一個類的方法來實現(xiàn)的。
在想項目開發(fā)牺六,會遇到這么一個需求:點擊一個按鈕變亮,其他按鈕變暗汗捡,再點擊變亮的按鈕淑际,按鈕又會朝上,再點擊又會朝下扇住。這個需求不算大春缕,也不難,找第三方庫又顯得大才小用了艘蹋。
如圖-1所示淡溯,按鈕有3個狀態(tài),默認狀態(tài)簿训,選中向上狀態(tài)咱娶,選中向下狀態(tài)米间。選中向下的狀態(tài),美工沒有給膘侮,所以屈糊,這里要自己變換(剛好可以把業(yè)務(wù)變的復(fù)雜點)。
思路
給UIView擴展一個字典琼了,這個字典里key存狀態(tài)逻锐,value存閉包(現(xiàn)在swift的closure可以轉(zhuǎn)成Any類型了)如下圖-2所示
這里我決定把這個字典屬性私有,通過下面圖-3兩個方法來使用字典(我覺得這樣做更容易閱讀雕薪。添加狀態(tài)昧诱,執(zhí)行狀態(tài))
最后我們還需要一個記錄當前狀態(tài)的屬性,還是用runtime來做
修改executeState 的方法 如下圖-5
先看效果圖
關(guān)于這些button的點擊事件如圖-6
根據(jù)button的當前的狀態(tài)所袁,然后去執(zhí)行應(yīng)該切換到的狀態(tài)的closure
看這些代碼盏档,是不是覺得代碼清晰了很多。
我們只要去配置下 "normal" "selected_up" "selected_down" 的狀態(tài)就使用這些state的閉包了燥爷。
func setupBtnState() {
/**
給每個button添加一個默認的狀態(tài)
*/
Abtn.addState("normal") { [weak self] in
self?.Abtn.isSelected = false
self?.Abtn.imageView?.transform = .init(rotationAngle: CGFloat(0))
}
Bbtn.addState("normal") { [weak self] in
self?.Bbtn.isSelected = false
self?.Bbtn.imageView?.transform = .init(rotationAngle: CGFloat(0))
}
Cbtn.addState("normal") { [weak self] in
self?.Cbtn.isSelected = false
self?.Cbtn.imageView?.transform = .init(rotationAngle: CGFloat(0))
}
/**
給每個button添加選中向上的狀態(tài)
*/
Abtn.addState("selected_up") { [weak self] in
self?.Abtn.isSelected = true
self?.Abtn.imageView?.transform = .init(rotationAngle: CGFloat(0))
//其他的兩個按鈕變成默認的狀態(tài)
self?.Bbtn.executeState("normal")
self?.Cbtn.executeState("normal")
}
Bbtn.addState("selected_up") { [weak self] in
self?.Bbtn.isSelected = true
self?.Bbtn.imageView?.transform = .init(rotationAngle: CGFloat(0))
//其他的兩個按鈕變成默認的狀態(tài)
self?.Abtn.executeState("normal")
self?.Cbtn.executeState("normal")
}
Cbtn.addState("selected_up") { [weak self] in
self?.Cbtn.isSelected = true
self?.Cbtn.imageView?.transform = .init(rotationAngle: CGFloat(0))
//其他的兩個按鈕變成默認的狀態(tài)
self?.Bbtn.executeState("normal")
self?.Abtn.executeState("normal")
}
/**
給每個button添加選中向下的時狀態(tài)蜈亩。
*/
Abtn.addState("selected_down") { [weak self] in
self?.Abtn.imageView?.transform = .init(rotationAngle: CGFloat(M_PI))
/**
只有在選中向上的情況下才能變成選中向下。
根據(jù)需求來選擇該狀態(tài)時的樣式前翎,以及其他視圖的樣式
self?.Abtn.isSelected = true
self?.Bbtn.executeState("normal")
self?.Cbtn.executeState("normal")
*/
}
Bbtn.addState("selected_down") { [weak self] in
self?.Bbtn.imageView?.transform = .init(rotationAngle: CGFloat(M_PI))
}
Cbtn.addState("selected_down") { [weak self] in
self?.Cbtn.imageView?.transform = .init(rotationAngle: CGFloat(M_PI))
}
}
雖然配置代碼有點多稚配,但是方便修改,而且可以嵌套執(zhí)行港华。比如點擊Cbtn的時候還要請求一些數(shù)據(jù)道川,就可以把這些邏輯添加到狀態(tài)selected_down下。