LMForm - iOS表單配置框架

LMForm

背景

通常啡氢,將一個頁面需要編輯/錄入多項信息的頁面稱為表單。iOS 實現(xiàn)表單大多數(shù)基于TableView,麻煩的是需要在UITableViewDataSource或者UITableViewDelegate的代理方法中寫很多if-else掰曾,與cell耦合嚴(yán)重,不易獲取用戶已編輯的數(shù)據(jù)旭蠕。如果表單頁面的配置數(shù)據(jù)從服務(wù)端返回,不易實現(xiàn)旷坦。

1. 介紹

LMForm 是基于MVVM輕量級表單配置框架掏熬,把數(shù)據(jù)和事件整合為一個model,實現(xiàn)cell與model的綁定塞蹭,只需操作model便可配置表單孽江。項目地址:https://github.com/MaricleZhang/LMForm.git

2. 結(jié)構(gòu)

image
  • LMFormTypeManager : 負(fù)責(zé)管理類型與cellClass
  • LMFormModel:cell 的配置信息,事件回調(diào)番电,數(shù)據(jù)校驗回調(diào)
  • Cell:遵循LMFormCellProtocol協(xié)議,實現(xiàn)不同的cell
  • LMFormTableView :注冊cell類型辆琅,通過model漱办,渲染表單
  • LMFormValidator:負(fù)責(zé)對數(shù)據(jù)的校驗

3. 功能

  1. 支持動態(tài)配置model來實現(xiàn)表單。
  2. 支持配置文本婉烟、輸入框娩井、選擇器、日期選擇似袁、地址選擇等洞辣。
  3. 支持快速提取數(shù)據(jù)。
  4. 支持?jǐn)?shù)據(jù)校驗昙衅,可自定義校驗格式扬霜。
  5. 支持完全自定義cell類型。

4. 預(yù)覽

form.gif

5. 安裝

CocoaPods

在 Podfile 中進行如下導(dǎo)入:

pod 'LMForm'

安裝

pod install

6. 使用

在項目中導(dǎo)入#import "LMForm.h"

1. 配置數(shù)據(jù)源

目前項目中集成以下類型:

類型 宏定義 Cell Class
文本 kFormTypeText LMFormCell
輸入框 kFormTypeInput LMFormInputCell
選擇器 kFormTypeSelector LMFormSelectorCell
日期選擇器 kFormTypeDate LMDateCell
地址輸入框 kFormTypeAddressInput LMFormAddressInputCell

可根據(jù)需求來選擇對應(yīng)的類型而涉,例如輸入框的model配置代碼如下:

  // 輸入框
- (LMFormModel *)loadInput
{
    LMFormModel *model = [LMFormModel new];
    model.formType = kFormTypeInput;
    model.title = @"手機號";
    model.key = @"mobile";
    model.value = @"";
    model.placeholder = @"請輸入手機號";
    model.height = LM_XX_6(50);
    model.message = @"請輸入正確的手機號";
    model.limitLength = 11;
    model.validateBlock = ^BOOL(LMFormModel * _Nullable model) {
        if (![LMFormValidator isMobile:model.value])
        {
            [LMWindowHud showHud:model.message];
            return NO;
        }
        return YES;
    };
    return model;
}

可根據(jù)需要設(shè)置UI著瓶,輸入限制長度,自定義校驗等啼县。

2. 創(chuàng)建tableview

創(chuàng)建基于LMFormTableView 的tableview材原,并且賦值渲染數(shù)據(jù),表單的創(chuàng)建完成季眷。

    self.tableView.dataArray = self.dataArray;

3. 校驗數(shù)據(jù)

提交時余蟹,對數(shù)據(jù)源進行自定義校驗,校驗的邏輯是對model.validateBlock遍歷回調(diào)子刮。

/**
 對數(shù)據(jù)源校驗

 @param dataArray 數(shù)據(jù)源
 @return 全部校驗通過返回YES威酒,否則返回NO。
 */
+ (BOOL)validateDataArray:(NSArray<LMFormModel *> *)dataArray
{
    for (LMFormModel * _Nonnull obj in dataArray)
    {
        if (obj.validateBlock)
        {
            if (!obj.validateBlock(obj)) return NO;
        }
    }
    return YES;
}

4. 獲取數(shù)據(jù)源

因為LMFormTableView中的cell與model綁定,只需遍歷獲取value即可兼搏。

7. Cell 類型的介紹

1. LMFormCell

基類cell:其他類型cell繼承該cell卵慰,主要功能顯示文本,不可編輯佛呻∩雅螅可根據(jù)需求配置相應(yīng)UI和數(shù)據(jù)。

- (void)configModel:(LMFormModel *)model
{
    self.model = model;
    
    // data
    self.titleLabel.text = model.title;
    self.textField.placeholder = model.placeholder;
    self.textField.text = model.value;
    if (model.limitLength)
    {
        self.textField.limitLength = @(model.limitLength);
    }
    
    // UI
    self.line.hidden = model.hiddenLine;
    self.line.backgroundColor = LM_ObjDefault(model.separatorLineColor, LM_UIColorFromHEX(0xF4F4F4));
    self.titleLabel.textColor = LM_ObjDefault(model.leftTextColor, LM_UIColorFromHEX(0x666666));
    self.textField.textColor = LM_ObjDefault(model.rightTextColor, LM_UIColorFromHEX(0x333333));
    self.titleLabel.font = LM_ObjDefault(model.leftLabelFont, [UIFont systemFontOfSize:LM_XX_6(14)]);
    self.titleLabel.font = LM_ObjDefault(model.rightLabelFont, [UIFont systemFontOfSize:LM_XX_6(14)]);
}

2. LMFormInputCell

輸入Cell:可以編輯吓著,可以對輸入長度限制鲤嫡,輸入的text更新為model的value。

- (void)textDidChanged:(UITextField *)textField
{
    self.model.value = textField.text;
    if (self.model.valueDidChangedBlock)
    {
        self.model.valueDidChangedBlock(textField.text);
    }
}

3. LMFormSelectorCell

選擇器Cell:可以選擇對應(yīng)的item,需要配置數(shù)據(jù)NSArray<NSString *> *selectList,點擊cell底部彈窗pickerView

- (void)tapSelectedAction
{
    LMDefaultPickerView *pickView = [[LMDefaultPickerView alloc] initWithDataArray:self.model.selectList];
    @weakify(self)
    [LMPopupView showPopupViewWithPickView:pickView title:self.model.placeholder confirmBlock:^{
        @strongify(self)
        NSString *text = self.model.selectList[pickView.selectIndex];
        self.model.value = text;
        self.textField.text = text;
        if (self.model.valueDidChangedBlock)
        {
            self.model.valueDidChangedBlock(text);
        }
    } cancelBlock:^{
        
    }];
}

4. LMDateCell

選擇日期Cell:與選擇cell類似绑莺,底部彈窗datePickerView暖眼。目前只支持年月日。

- (void)tapSelectedAction
{
    @weakify(self)
    [LMPopupView showPopupViewWithPickView:self.datePicker title:self.model.placeholder confirmBlock:^{
        @strongify(self)
        NSDate *date = self.datePicker.date;
        NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
        [formatter setDateFormat:self.model.dateFormat ?: @"yyyy-MM-dd"];
        NSString *text = [formatter stringFromDate:date];
        self.model.value = text;
        self.textField.text = text;
    } cancelBlock:^{
        
    }];
}

5. LMFormAddressInputCell

地址輸入cell:主要用來輸入較多數(shù)字的信息纺裁,分兩行顯示诫肠。

6.自定義cell

創(chuàng)建

LMForm 支持cell的完全自定義,創(chuàng)建的自定義cell需要遵循協(xié)議LMFormCellProtocol欺缘,
協(xié)議的方法必須實現(xiàn)栋豫,在自定義的cell中實現(xiàn)配置數(shù)據(jù)。如果LMFormModel中的屬性不能滿足需求谚殊,可以創(chuàng)建LMFormModel分類添加或者繼承丧鸯。個人比較推薦分類的做法。

/** 根據(jù)model 配置對應(yīng)的cell  */
- (void)configModel:(LMFormModel *)model;

注冊

LMForm 維護一張注冊表建立key與cellClass的一一對應(yīng)關(guān)系嫩絮,單例LMFormTypeManager中的keyCellTypes就是這個注冊表丛肢。注冊方法為

/**
 自定義cell時注冊方法,同一種cell只需要注冊一次剿干。cls 需繼承UITableViewCell

 @param cls cell class
 @param key key
 */
- (void)registerCellClass:(Class)cls forKey:(NSString *)key;

需要注意的是注冊表是個字典蜂怎,key的定義不能重復(fù)

8. 項目地址:Demo

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末怨愤,一起剝皮案震驚了整個濱河市派敷,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌撰洗,老刑警劉巖篮愉,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異差导,居然都是意外死亡试躏,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進店門设褐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來颠蕴,“玉大人泣刹,你說我怎么就攤上這事∠唬” “怎么了椅您?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長寡键。 經(jīng)常有香客問我掀泳,道長,這世上最難降的妖魔是什么西轩? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任员舵,我火速辦了婚禮,結(jié)果婚禮上藕畔,老公的妹妹穿的比我還像新娘马僻。我一直安慰自己,他們只是感情好注服,可當(dāng)我...
    茶點故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布韭邓。 她就那樣靜靜地躺著,像睡著了一般溶弟。 火紅的嫁衣襯著肌膚如雪仍秤。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天可很,我揣著相機與錄音,去河邊找鬼凰浮。 笑死我抠,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的袜茧。 我是一名探鬼主播菜拓,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼笛厦!你這毒婦竟也來了纳鼎?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤裳凸,失蹤者是張志新(化名)和其女友劉穎贱鄙,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體姨谷,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡逗宁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了梦湘。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片瞎颗。...
    茶點故事閱讀 38,617評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡件甥,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出哼拔,到底是詐尸還是另有隱情引有,我是刑警寧澤,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布倦逐,位于F島的核電站譬正,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏僻孝。R本人自食惡果不足惜导帝,卻給世界環(huán)境...
    茶點故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望穿铆。 院中可真熱鬧您单,春花似錦、人聲如沸荞雏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽凤优。三九已至悦陋,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間筑辨,已是汗流浹背俺驶。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留棍辕,地道東北人暮现。 一個月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像楚昭,于是被迫代替她去往敵國和親栖袋。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,486評論 2 348