LMForm - iOS表單配置框架

背景

一般,將一個頁面須要編輯/錄入多項信息的頁面稱爲表單。iOS 實現表單大多數基於TableView,麻煩的是須要在UITableViewDataSource或者UITableViewDelegate的代理方法中寫不少if-else,與cell耦合嚴重,不易獲取用戶已編輯的數據。若是表單頁面的配置數據從服務端返回,不易實現。git

1. 介紹

LMForm 是基於MVVM輕量級表單配置框架,把數據和事件整合爲一個model,實現cell與model的綁定,只需操做model即可配置表單。項目地址:github.com/MaricleZhan…github

2. 結構

  • LMFormTypeManager : 負責管理類型與cellClass
  • LMFormModel:cell 的配置信息,事件回調,數據校驗回調
  • Cell:遵循LMFormCellProtocol協議,實現不一樣的cell
  • LMFormTableView :註冊cell類型,經過model,渲染表單
  • LMFormValidator:負責對數據的校驗

3. 功能

  1. 支持動態配置model來實現表單。
  2. 支持配置文本、輸入框、選擇器、日期選擇、地址選擇等。
  3. 支持快速提取數據。
  4. 支持數據校驗,可自定義校驗格式。
  5. 支持徹底自定義cell類型。

4. 預覽

form.gif

5. 安裝

CocoaPods

在 Podfile 中進行以下導入:bash

pod 'LMForm'
複製代碼

安裝框架

pod install
複製代碼

6. 使用

在項目中導入#import "LMForm.h"ui

1. 配置數據源

目前項目中集成如下類型:spa

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

可根據需求來選擇對應的類型,例如輸入框的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;
}
複製代碼

可根據須要設置UI,輸入限制長度,自定義校驗等。code

2. 建立tableview

建立基於LMFormTableView 的tableview,而且賦值渲染數據,表單的建立完成。orm

self.tableView.dataArray = self.dataArray;
複製代碼

3. 校驗數據

提交時,對數據源進行自定義校驗,校驗的邏輯是對model.validateBlock遍歷回調。cdn

/**
 對數據源校驗

 @param dataArray 數據源
 @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. 獲取數據源

由於LMFormTableView中的cell與model綁定,只需遍歷獲取value便可。

7. Cell 類型的介紹

1. LMFormCell

基類cell:其餘類型cell繼承該cell,主要功能顯示文本,不可編輯。可根據需求配置相應UI和數據。

- (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:能夠選擇對應的item,須要配置數據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:主要用來輸入較多數字的信息,分兩行顯示。

6. LMFormTextViewCell

可變輸入框cell:cell高度可隨textview 高度變化而變化

7.自定義cell

建立

LMForm 支持cell的徹底自定義,建立的自定義cell須要遵循協議LMFormCellProtocol, 協議的方法必須實現,在自定義的cell中實現配置數據。若是LMFormModel中的屬性不能知足需求,能夠建立LMFormModel分類添加或者繼承。我的比較推薦分類的作法。

/** 根據model 配置對應的cell  */
- (void)configModel:(LMFormModel *)model;
複製代碼

註冊

LMForm 維護一張註冊表創建key與cellClass的一一對應關係,單例LMFormTypeManager中的keyCellTypes就是這個註冊表。註冊方法爲

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

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

須要注意的是註冊表是個字典,key的定義不能重複

8. 項目地址:Demo

相關文章
相關標籤/搜索