設計組合型UI控件中的編程思想:UI拋出事件-數據驅動UI

1. 展示型控件、交互性控件、組合型控件

CocoaTouch框架里提供的UI控件分為兩類:一類是是用于展示的控件UIView及其子類,另外一類是用于交互的控件UIControl及其子類。我們在實際開發中經常會遇到將兩類控件組合在一起封裝成一個自定義的控件,這種控件可以交互,并對交互的結果進行展示,例如購物車里的數量編輯條控件,點擊?和?按鈕,中間的數量label會相應的更新;再例如文檔里的頁切換控件,點擊←和→按鈕,中間的頁碼label也會相應的更新。接下來以我在實際開發中遇到的一個需求來分析一下這類組合型控件在設計時應該遵循的編程思想。


count_bar.jpg

2. 案例導入

價格設置條。產品需求是價格區間在0.1~9.9,每次加和減的梯度是0.1。


price_bar.png

3. 不好的設計

先說一個不好的設計,關鍵部分代碼如下

  var priceChangeHandle: ((_ price: CGFloat) -> Void)?    
  var price: CGFloat {
        didSet {
            priceLabel.text = String(format: "%.1f", price)
            priceChangeHandle?(price)
        }
    }
  init(frame: CGRect, price: CGFloat, max: CGFloat = 99.9, min: CGFloat = 0.1, degree: CGFloat = 0.1 ) {
   ...
  }

這個設計的思路是 價格區間和操作梯度由初始化時自定義提供,內部維護一個price變量,當點擊加或者減的時候先判斷修改后的price是否在區間內,滿足條件就去修改,然后去修改顯示標簽,并通過一個閉包告知使用者數據發生變化。

這個設計不好的地方在于控件內部對交互的結果作出了處理。控件只應該負責拋出事件提供跟新UI的方法,而不是通過復雜的初始化方法提供變量用來自己解釋交互的結果,這樣定義的控件不符合編程思想,使用起來也是局限性非常大。

4. 合理的設計

自定義組合控件

 enum EditAction {
        case increase
        case decrease
    }
 override init(frame: CGRect) {
   super.init(frame: frame)
   decreaseItem.editHandle = { [weak self] in
            guard let self = self else {
                return
            }
            if let handle = self.editActionHandle {
                self.amountLabel.text = handle(.decrease)
            }
    }
   increaseItem.editHandle = { [weak self] in
            guard let self = self else {
                return
            }
            if let handle = self.editActionHandle {
                self.amountLabel.text = handle(.increase)
            }
    }
}
func regist(editActionHandle: @escaping ((_ action: EditAction) -> String)) {
        self.editActionHandle = editActionHandle
 }

使用控件

priceEditBar.regist { [weak self] action -> String in
            guard let self = self else { return "0.1" }
            switch action {
            case .increase:
                if abs(self.price-0.9) > 0.01 {
                    self.price += 0.1
                }
            case .decrease:
                if abs(self.price-0.1) > 0.01 {
                    self.price -= 0.1
                }
            }
            return String(format: "%.1f", self.price)
 }

新的設計把這個組合類控件的兩個功能拆分開了,操作控件之后內部只會拋出事件,而不會去處理事件,比如點擊了?按鈕,那這個類只負責告訴外界有這個事件發生,具體怎么解釋這個事件是外界的職責。外界解釋好這個事件之后(更新數據),再由外界根據數據去更新控件的顯示內容。
這樣做有幾個好處:

  1. 不需要復雜的初始化方法提供用于邏輯控制的變量(像例子里的取值區間和操作梯度)
  2. 不對邏輯進行處理的控件使得其本身更簡潔易用、復用性更高。
  3. 符合 “UI拋出事件-數據驅動UI”的編程思想

5. 總結

設計控件時一定要避免事件直接驅動UI,而是將控件的職責分成兩部分:向外界拋出事件向外界提供更新UI的方法,這兩者之間的邏輯應該交由外界去處理。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,443評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,530評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,407評論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,981評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,759評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,204評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,263評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,415評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,955評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,782評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,983評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,222評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,650評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,892評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,675評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,967評論 2 374