CBFormController 0.3.0

CBFormController 0.3.0

测试已测试
Lang语言 Obj-CObjective C
许可证 MIT
Released上次发布2016年10月

Cameron BellJulien Guerinet 维护。



 
依赖项
FontAwesome~> 4.3.0
UITextView+Placeholder>= 0
MZFormSheetController~> 3.1
MLPAutoCompleteTextField= 1.5
 

  • by
  • Cameron Bell

CBFormController 是一个用于 iOS 的灵活、可定制的表单控制器,用 Objective-C 编写。

安装

CBFormController 通过 CocoaPods 提供。要安装它,只需将以下行添加到您的 Podfile 中

pod "CBFormController"

使用方法

要运行示例项目,请克隆仓库,然后首先从 Example 目录中运行 pod install

创建表单

CBFormController 是提供表单的视图控制器。它不需要用户设置 xib 或任何视图。

要创建 CBFormController,创建 CBFormController 的子类。

然后重写以下函数来创建您的表单,通过创建 CBFormItems 并以二维数组的格式返回它们来实现

-(NSArray *)getFormConfiguration {

    //Choose the way you want your form to handle saving
    [self setEditMode:CBFormEditModeEdit];

    //Create an array of sections
    NSMutableArray *sections = [[NSMutableArray alloc] init];

    //Create a Text form item
    CBText *firstName = [[CBText alloc]initWithName:@"firstName"];
    [firstName setTitle:@"First Name"];
    [firstName setIcon:[FAKFontAwesome userIconWithSize:19]];
    [firstName setInitialValue:_appDelegate.profile.firstName];
    [firstName setValidation:^BOOL(NSString *value) {
        NSString *errString = (NSString*)[Profile validateFirstName:value];
        if (errString) {
            [self showValidationErrorWithMessage:errString];
            return NO;
        }
        return YES;
    }];
    [firstName setSave:^(NSString *value) {
        _appDelegate.profile.firstName = value;
    }];

    CBText *lastName = [[CBText alloc]initWithName:@"lastName"];
    [lastName setTitle:@"Last Name"];
    [lastName setInitialValue:_appDelegate.profile.lastName];
    [lastName setSave:^(NSString *value) {
        _appDelegate.profile.lastName = value;
    }];

    //Create a picker form item
    CBPicker *gender = [[CBPicker alloc]initWithName:@"gender"];
    [gender setTitle:@"Gender"];
    [gender setInitialValue:_appDelegate.profile.gender == MALE ? GENDER_MALE : GENDER_FEMALE];
    [gender setIcon:[FAKFontAwesome transgenderIconWithSize:18]];
    [gender setItems:@[@"Male", @"Female"]];
    [gender setSave:^(NSString *value) {
        _appDelegate.profile.gender = [value isEqualToString:GENDER_MALE] ? MALE : FEMALE;
    }];

    //Create a date form item
    CBDate *birthDate = [[CBDate alloc]initWithName:@"birthdate"];
    [birthDate setTitle:@"Birthdate"];
    [birthDate setInitialValue:_appDelegate.profile.birthDate];
    [birthDate setIcon:[FAKFontAwesome calendarIconWithSize:18]];
    [birthDate setValidation:^BOOL(NSDate *value) {
        NSString *errString = (NSString*)[Profile validateBirthDate:value];
        if (errString) {
            [self showValidationErrorWithMessage:errString];
            return NO;
        }
        return YES;
    }];
    [birthDate setSave:^(NSDate *value) {
        _appDelegate.profile.birthDate = value;
    }];

    //Add the created form items to arrays containing the form items that should be grouped together
    NSMutableArray *profileSection = [[NSMutableArray alloc] initWithObjects:firstName,lastName, nil];
    NSMutableArray *genderSection = [[NSMutableArray alloc] initWithObjects:gender,birthDate, nil];

    //Add the section arrays to the sections array
    [sections addObjectsFromArray:@[profileSection, genderSection]];

    //If this form is being edited, show the user a delete button
    if (self.editing) {
        CBButton *deleteButton = [[CBButton alloc]initWithName:@"delete"];
        [sections addObject:@[deleteButton]];
        [deleteButton setButtonType:CBButtonTypeDelete];
        [continueButton setSelect:^{
            [self delete];
        }];
    }
    return sections;
}

表单项类型

CBText

CBDate

CBButton

buttonType 属性优先于 titleAlign 属性。

CBSwitch

CBComment

CBPicker

CBPopupPicker

CBFAQ (WIP)

CBView (WIP)

CBSegmentedControl (WIP)

CBAutoComplete (WIP)

CBCaption (WIP)

编辑/保存

编辑模式

CBFormController 有一个名为 editMode 的属性,它决定了用户是否可以编辑和保存表单。

//Enum for the different editing modes of the CBFormController
typedef NS_ENUM(NSInteger, CBFormEditMode) {
    CBFormEditModeEdit = 1,
    CBFormEditModeFrozen,
    CBFormEditModeSave,
    CBFormEditModeFree
};

-(NSArray *)getFormConfiguration 中,子类应调用: [self setEditMode:CBFormEditModeSave]; 来设置编辑模式。默认值为 CBFormEditModeFree。

CBFormController 还有一个名为 -(BOOL)editing; 的属性,用于跟踪表单是否可以当前编辑。

CBFormEditModeEdit

这种编辑模式在视图控制器的导航栏中提供一个编辑按钮,直到用户点击编辑按钮,用户不能更改表单项。编辑按钮变为保存按钮,当用户修改了数据后,在导航栏左侧出现取消按钮。

CBFormItem 有一个布尔属性 enabledWhenNotEditing,允许当表单控制器非编辑状态时,表单项可被编辑。CBButtons 默认此属性为 true。

CBFormEditModeFrozen

这种编辑模式不允许用户编辑任何字段,除非将 enabledWhenNotEditing 属性设置为 true。

CBFormEditModeSave

在此编辑模式中,CBFormController 总是处于可编辑状态。当用户修改表单时,导航栏右侧将出现一个保存按钮。

CBFormEditModeFree (WIP)

在此编辑模式中,没有保存按钮,表单始终可编辑。当用户进行修改时,它会立即进行验证并保存。

保存

当用户按下保存按钮时,会调用 CBFormController 的 -(BOOL)save; 函数。子类可以重写此函数,但如果要保留导航项功能,则必须记住调用 [super save]

当调用保存函数时,CBFormController 首先调用所有表单项的验证块(如果存在)。每个表单项都有机会通过返回 YES 或 NO 来在验证块中阻止保存调用,这取决于验证是否通过。如果没有为表单项提供验证块,则不执行验证。

如果验证通过,则在所有表单项上调用保存块。这就是子类应该处理将返回值保存回数据存储/模型的地方。

注意

无论何时按下保存、编辑或取消按钮,都会在 CBFormController 上调用 -(void)reloadEntireForm;。这意味着会再次调用 -(NSArray *)getFormConfiguration; 函数,子类有机会更改表单项的属性或添加或删除表单项。

自定义单元格集

CBFormController 允许您安装一个单元格集,它是一组扩展 CBFormItem 功能并提供单元格美学的类,通过每个单元格类型的 .xib 文件。

创建一个新的 CBCellSet

  1. 创建 CBCellSet 的子类
  2. 创建子类的实例并将其设置为 CBFormController 的 cellSet 属性
  3. 实现默认高度和默认两行高度(如适用)。
  4. 创建名为 "[子类名称][FormItemType枚举值]" 的单元格类(每个类必须有一个包含单个单元格的xib文件。)
  5. 使用Interface Builder配置每个单元格并关联其属性

创建新的CBFormItemType

  1. 创建CBFormItem的一个子类
  2. 把您的子类导入CBFormController
  3. 为新的类型创建一个CBCell的子类。例如:CBTextCell
  4. 在CBCell子类中实现 -(void)configureForFormItem:(CBText *)formItem;
  5. 创建CBCell子类的子类(例如:CBTextCell的子类)\[name of your CBCellSet subclass][formtype enum value]\(例如:CBCellSet2Text)
  6. 根据需要覆盖新的子类中的 -(void)configureForFormItem:(CBText *)formItem;,确保调用super。
  7. 为第二个子类创建一个具有相同名称的空xib文件。
  8. 在文件中创建一个单个的UITableViewCell,并将其类设置为第二个子类。
  9. 实现CBFormItem子类的方法
    • -(BOOL)isEdited;
    • -(CBFormItemType)type;
    • -(NSObject *)value;
    • -(void)setInitialValue:(NSObject *)value;
    • -(void)engage;
    • -(void)dismiss;
  10. 请确保处理参数和值可能为nil的情况。

具有动态高度的表单项

当您想使用动画更新单元格的高度时,请在CBFormController上调用[self updates];。

从CBCell Category创建CBCell的定制属性

当您想使您自定义的CBCellSet中的所有单元格具有相同的属性时,这很有用。这个属性可以是 IBOutlet,并且可以由interface builder链接。

  1. 在CBCell上定义一个category(例如:CBCell+CBCellSet1)
  2. 在实现之上,定义一个名为 [name of your property]Key 的 static char (例如:static char iconLabelKey;)
  3. 在category的interface中定义您的属性。您不能在.m文件中为此属性使用 @synthesize。
  4. 然后手动创建此属性的setter和getter,并在interface中包含它们的声明。(例如:-(void)setIconLabel:(UILabel *)iconLabel;-(UILabel *)iconLabel;
  5. 如下实现getter和setter
- (void)setIconLabel:(UILabel *)iconLabel {
    [self setCustomPropertyWithObject:iconLabel forKey:iconLabelKey];
}
- (UILabel *)iconLabel {
    return (UILabel *)[self getCustomPropertyWithKey:iconLabelKey];
}
  1. 如果此属性是 IBOutlet,您现在将能够使用Interface Builder连接定制属性。
  2. 如果您需要在一个CBCell的子类中访问此属性,那么将category导入到您想访问属性的那个类中。

依赖关系

  • pod 'UITextView+Placeholder'
  • pod 'MZFormSheetController', '~> 3.1'
  • FAKFontAwesome

贡献者

版本历史

请参阅 变更日志

许可

CBFormController可在MIT许可下使用。有关更多信息,请参阅LICENSE文件。