一、引言
表单视图是移动开发中十分常用的一种UI方式。在iOS开发中,系统的UITableView可以用来创建表单视图,其界面的渲染与逻辑的处理需要开发者实现许多代理方法。FXForms是一个第三方的表单创建工具,其通过配置的方式来进行表单界面的创建,并且其中为开发者封装好了各种常用类型的表单cell。
FXForms的github地址如下:[https://github.com/nicklockwood/FXForms](https://github.com/nicklockwood/FXForms)。
FXForms框架中提供了一个FXFormViewController视图控制器类,开发者可以直接编写继承于这个类的ViewController来便捷的创建表单界面,首先,FXForms是通过节点配置的方式来进行表单的创建的,表单中每一个cell都是一个节点,这个节点可以是简单的单节点,也可以是父节点,点击父节点后,会跳转新的视图控制器,父节点中可以进行层层嵌套。对于每一个节点,开发者可以设置一个节点类型,不同的节点类型将展现不同的UI,实现不同的功能。
FXForms中的节点由FXForm协议来进行配置,创建一个简单的表单视图,示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| @interface ViewController : FXFormViewController @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.formController.form = [MyForm new]; } @end
@interface MyForm : NSObject<FXForm> @property(nonatomic,strong)NSString * email; @property(nonatomic,strong)NSString * password; @property(nonatomic,assign)BOOL rememberMe; @end @implementation MyForm @end
|
上面的MyForm类中只定义了一些属性,并没有进行任何方法的实现,FXForms框架中实现了这样的功能,如果开发者不进行节点信息的配置,则FXForms会自动根据节点配置类中所有的属性来推断节点的类型,如上所示,NSString类型的属性会被自动推断成带文本框的cell,BOOL类型的属性会被自动推断成带UISwitch控件的cell。运行效果如下:
开发者可以为节点配置类中的每一个属性提供一个约定好的方法,在方法中对此属性对应的节点进行配置,这个约定好的方法名需要与属性对应,其格式是使用属性名加上Field,示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| @implementation MyForm
-(NSDictionary *)emailField{ return @{FXFormFieldType:FXFormFieldTypeDate}; } -(NSDictionary *)passwdField{ return @{FXFormFieldTitle:@"名称"}; } -(NSDictionary *)rememberMeField{ return @{FXFormFieldHeader:@"配置"}; } @end
|
运行工程,效果如下图所示:
返回的配置字典中可以用来配置的属性定义如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| UIKIT_EXTERN NSString *const FXFormFieldKey;
UIKIT_EXTERN NSString *const FXFormFieldType;
UIKIT_EXTERN NSString *const FXFormFieldClass;
UIKIT_EXTERN NSString *const FXFormFieldCell;
UIKIT_EXTERN NSString *const FXFormFieldTitle;
UIKIT_EXTERN NSString *const FXFormFieldPlaceholder;
UIKIT_EXTERN NSString *const FXFormFieldDefaultValue;
UIKIT_EXTERN NSString *const FXFormFieldOptions;
UIKIT_EXTERN NSString *const FXFormFieldTemplate;
UIKIT_EXTERN NSString *const FXFormFieldValueTransformer;
UIKIT_EXTERN NSString *const FXFormFieldAction;
UIKIT_EXTERN NSString *const FXFormFieldSegue;
UIKIT_EXTERN NSString *const FXFormFieldHeader;
UIKIT_EXTERN NSString *const FXFormFieldFooter;
UIKIT_EXTERN NSString *const FXFormFieldInline;
UIKIT_EXTERN NSString *const FXFormFieldSortable;
UIKIT_EXTERN NSString *const FXFormFieldViewController;
|
关于设置节点的类型,FXFormFieldType可以设置的值有如下几种:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| UIKIT_EXTERN NSString *const FXFormFieldTypeDefault;
UIKIT_EXTERN NSString *const FXFormFieldTypeLabel;
UIKIT_EXTERN NSString *const FXFormFieldTypeText;
UIKIT_EXTERN NSString *const FXFormFieldTypeLongText;
UIKIT_EXTERN NSString *const FXFormFieldTypeURL;
UIKIT_EXTERN NSString *const FXFormFieldTypeEmail;
UIKIT_EXTERN NSString *const FXFormFieldTypePhone;
UIKIT_EXTERN NSString *const FXFormFieldTypePassword;
UIKIT_EXTERN NSString *const FXFormFieldTypeNumber;
UIKIT_EXTERN NSString *const FXFormFieldTypeInteger;
UIKIT_EXTERN NSString *const FXFormFieldTypeUnsigned;
UIKIT_EXTERN NSString *const FXFormFieldTypeFloat;
UIKIT_EXTERN NSString *const FXFormFieldTypeBoolean;
UIKIT_EXTERN NSString *const FXFormFieldTypeOption;
UIKIT_EXTERN NSString *const FXFormFieldTypeDate;
UIKIT_EXTERN NSString *const FXFormFieldTypeTime;
UIKIT_EXTERN NSString *const FXFormFieldTypeDateTime;
UIKIT_EXTERN NSString *const FXFormFieldTypeImage;
|
FXForms中也提供了许多封装好的cell,列举如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| @interface FXFormDefaultCell : FXFormBaseCell @end
@interface FXFormTextFieldCell : FXFormBaseCell @property (nonatomic, readonly) UITextField *textField; @end
@interface FXFormTextViewCell : FXFormBaseCell @property (nonatomic, readonly) UITextView *textView; @end
@interface FXFormSwitchCell : FXFormBaseCell @property (nonatomic, readonly) UISwitch *switchControl; @end
@interface FXFormStepperCell : FXFormBaseCell @property (nonatomic, readonly) UIStepper *stepper; @end
@interface FXFormSliderCell : FXFormBaseCell @property (nonatomic, readonly) UISlider *slider; @end
@interface FXFormDatePickerCell : FXFormBaseCell @property (nonatomic, readonly) UIDatePicker *datePicker; @end
@interface FXFormImagePickerCell : FXFormBaseCell @property (nonatomic, readonly) UIImageView *imagePickerView; @property (nonatomic, readonly) UIImagePickerController *imagePickerController; @end
@interface FXFormOptionPickerCell : FXFormBaseCell @property (nonatomic, readonly) UIPickerView *pickerView; @end
@interface FXFormOptionSegmentsCell : FXFormBaseCell @property (nonatomic, readonly) UISegmentedControl *segmentedControl; @end
|
还有一点需要注意,如果是继承与FXFormViewController的视图控制器,其节点设置的action方法要在视图控制器中进行实现。
三、通过协议方法来进行节点配置
上面演示的创建表格视图的方式是在节点配置类中创建属性,分别配置属性的节点信息来创建每一个cell,开发者也可以不创建属性,或者创建属性但是不以属性为节点来进行cell配置,使用FXFrom协议的方法,也可以完成节点的创建和配置,示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| @interface MyForm : NSObject<FXForm> @end @implementation MyForm
- (NSArray *)fields { return @[ @{FXFormFieldKey: @"email", FXFormFieldTitle: @"email"}, @{FXFormFieldKey: @"phone", FXFormFieldTitle: @"phone"}, @{FXFormFieldKey: @"address", FXFormFieldTitle: @"address"}, @{FXFormFieldKey: @"name", FXFormFieldTitle: @"name"} ]; }
@end
|
效果如下:
-(NSArray *)fields方法是FXForm协议中的一个方法,在这个方法中,可以直接进行节点的创建和配置,FXForm协议中还提供了两个方法,意义如下:
1 2 3 4
| - (NSArray *)extraFields;
- (NSArray *)excludedFields;
|
节点也可以进行复合,例如可以将一个节点配置类作为属性设置给另一个节点配置类,示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| @interface SubForm : NSObject<FXForm> @property(nonatomic,assign)NSInteger age; @property(nonatomic,assign)NSDate * date; @end @implementation SubForm @end
@interface MyForm : NSObject<FXForm> @property(nonatomic,strong)NSString * email; @property(nonatomic,strong)NSString * passwd; @property(nonatomic,assign)BOOL rememberMe;
@property(nonatomic,strong)SubForm * subForm; @end @implementation MyForm @end
|
子节点会被默认包装在新的视图控制器中,也可以设置FXFormFieldInline为@YES来使其复合进当前视图控制器,效果如下:
四、关于自定义视图控制器
如果开发者的视图控制器并不是继承于FXFormViewController,也可以使用FXForms来快捷的创建表单视图,开发者自定义的视图控制器需要遵守FXFormControllerDelegate协议,示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| @interface ViewController : UIViewController<FXFormControllerDelegate>
@property(nonatomic,strong)UITableView * tableView;
@property(nonatomic,strong)FXFormController * formController; @end @implementation ViewController
- (void)viewDidLoad { [super viewDidLoad]; self.tableView = [[UITableView alloc]initWithFrame:self.view.frame style:UITableViewStyleGrouped]; self.formController = [[FXFormController alloc] init]; self.formController.tableView = self.tableView; self.formController.delegate = self; self.formController.form = [[MyForm alloc] init]; self.formController.form = [MyForm new]; [self.view addSubview:self.tableView]; } @end
|
上面的代码极大了简化了ViewController中的代码量。
五、对Cell进行属性设置
在进行节点属性字典的配置时,可以通过访问属性路径的方式来对cell的属性进行一些配置,例如:
1 2 3
| -(NSDictionary *)passwdField{ return @{@"textLabel.textColor":[UIColor redColor]}; }
|
专注技术,热爱生活,交流技术,也做朋友。
——珲少 QQ群:203317592