FXForms 1.2.14

FXForms 1.2.14

测试已测试
语言语言 Obj-CObjective C
许可证 zlib
发布最新发布2015年11月

Nick Lockwood 维护。



FXForms 1.2.14

  • 作者
  • Nick Lockwood

目的

FXForms 是一个 Objective-C 库,可轻松在 iOS 上创建基于表格的表单。它非常适合设置页面或数据录入任务。

与其他解决方案不同,FXForms 直接与您提供的强类型数据模型协同工作(而不是字典或复杂的 dataSource 协议),并尽可能从您的模型中推断信息,以避免重复类型信息的繁琐过程。

Screenshot of BasicExample

支持的 iOS 及 SDK 版本

  • 支持的构建目标 - iOS 9.0 (Xcode 7.0, Apple LLVM 编译器 7.0)
  • 最早支持的部署目标 - iOS 7.0
  • 最早兼容的部署目标 - iOS 5.0

注意:“支持”意味着库已与该版本进行过测试。“兼容”意味着库应在此 iOS 版本上运行(即它不依赖于任何不可用的 SDK 功能),但不再对此版本进行兼容性测试,可能需要调整或错误修复才能正确运行。

ARC 兼容性

FXForms 需要ARC。如果您想在非ARC项目中使用 FXForms,只需向 FXForms.m 类中添加 -fobjc-arc 编译器标志。要做到这一点,请转到目标设置中的构建阶段选项卡,打开编译源代码组,在列表中双击 FXForms.m,然后在弹出窗口中输入 -fobjc-arc

如果您想将整个项目转换为 ARC,请在 FXForms.m 中注释掉 #error 行,然后运行 Xcode 中的 Edit > Refactor > Convert to Objective-C ARC... 工具,并确保所有您希望使用 ARC 的文件都已选中(包括 FXForms.m)。

创建表单

要创建表单对象,只需创建任何新的符合 FXForm 协议的 NSObject 子类,如下所示

@interface MyForm : NSObject <FXForm>

@end

FXForm 协议没有强制方法或属性。FXForms 库将检查您的对象并识别所有公共和私有属性,并使用它们来生成表单。例如,如果您想有一个包含“电子邮件”、“密码”字段和“记住我”开关的表单;您将按照以下方式定义它

@interface MyForm : NSObject <FXForm>

@property (nonatomic, copy) NSString *email;
@property (nonatomic, copy) NSString *password;
@property (nonatomic, assign) BOOL rememberMe;

@end

这就是您必须做的全部内容。FXForms 真的非常智能;比您想象的要聪明得多

  • 字段将按照您在类中声明的顺序显示
  • 字段将自动分配适当的控件类型,例如,rememberMe 字段将显示为 UISwitch,电子邮件字段将自动拥有 UIKeyboardTypeEmailAddress 类型的键盘,而密码字段将自动启用 secureTextEntry
  • 字段标题基于键名,但 CamelCase 将自动转换为标题案,并智能处理缩写词等。
  • 修改表单中的值将自动将这些值分配回您的模型对象。如果需要执行附加逻辑,您可以使用自定义设置器方法和/或 KVO 来截获更改。
  • 如果您的表单包含子表单(符合 FXForm 协议的属性)或视图控制器(例如条款和条件页面),如果它们为 nil,它们将自动实例化 - 无需设置默认值。

所有默认行为都是通过使用 Objective-C 的运行时 API 检查属性类型和名称推断出来的,但如果您愿意,也可以覆盖它们 - 这将在稍后的“调整表单行为”中介绍。

显示表单(基础)

要在视图控制器中显示您的表单,您有两个选择:《code>FXForms提供了一个名为 FXFormViewControllerUIViewController 子类,设计得尽可能简单。要设置 FXFormViewController,只需像平常一样创建它,并按以下方式设置您的表单

FXFormViewController *controller = [[FXFormViewController alloc] init];
controller.formController.form = [[MyForm alloc] init];

然后您可以像任何普通视图控制器一样显示表单控制器。《code>FXFormViewController 包含一个 UITableView,它将自动创建所需的表格视图。如果您更喜欢的话,您可以将自己的 UITableView 分配给 tableView 属性并使用它。您甚至可以初始化一个包含创建 UITableView 的 nib 文件的 FXFormViewController

就像常规的 UIViewControllerUITableViewController 一样,《code>FXFormViewController 是可子类化的。在大多数情况下,您可能会想要子类化 FXFormViewController 以添加您自己的表单设置逻辑和操作处理器。

FXFormViewController(或子类)放入 UINavigationController 中是一个好主意。这不是强制性的,但如果表单包含子表单,这些子表单将被推向其 navigateController,如果没有,表单则不会显示。

UITableViewController 类似,《code>FXFormViewController 通常将 tableView 作为控制器的主视图。与 UITableViewController 不同的是,它 不必 是的 - 如果您更喜欢,您可以做出您的 tableView 成为主要视图的子视图。

UITableViewController 类似,《code>FXFormViewController 实现了 UITableViewDelegate 协议,因此,如果您子类化它,您可以覆盖 UITableViewDelegateUIScrollViewDelegate 方法以实现自定义行为。《code>FXFormViewController 实际上不是 tableView 的直接委托,而是其 formController(FXFormController 实例)的委托。formController 充当 tableView 的委托和资源库,并通过 FXFormControllerDelegate 协议将 UITableViewDelegate 方法代理回 FXFormViewController

UITableViewController 不同,《code>FXFormViewController 不实现 UITableViewDataSource 协议。这完全由 FXFormController 处理,不建议您尝试覆盖或截获任何数据源方法。

显示表单(高级)

FXFormViewController 非常灵活,但有时被迫使用特定的基本控制器类却不太方便。例如,您可能希望所有控制器都使用一个通用的基本类,或者在一个没有关联控制器的视图中显示表单。

在前一种情况下,您可以添加一个FXFormViewController作为子控制器,但在后一种情况下则不起作用。要在不使用FXFormViewController的情况下使用FXForms,可以直接使用FXFormController。要使用FXFormController显示表单,只需设置表单和tableView属性,其余的它都会处理。您可以选择绑定FXFormController的代理属性来接收事件的通知。

以这种方式使用自定义表单视图控制器时,仍然会为您处理一些交互(例如,当键盘出现时调整TableView的content inset),但您还需要自己添加其他视图逻辑,例如当UIViewController在屏幕上出现时重新加载表。

以下是一个自定义表单视图控制器的示例代码

@interface MyFormViewController : UIViewController <FXFormControllerDelegate>

@property (nonatomic, strong) IBOutlet UITableView *tableView;
@property (nonatomic, strong) FXFormController *formController;

@end

@implementation MyFormViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    //we'll assume that tableView has already been set via a nib or the -loadView method
    self.formController = [[FXFormController alloc] init];
    self.formController.tableView = self.tableView;
    self.formController.delegate = self;
    self.formController.form = [[MyForm alloc] init];
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    //reload the table
    [self.tableView reloadData];
}

@end

调整表单行为

FXForm的最大优势是尽可能地猜测,以消除工作量。然而,它不能猜测所有内容,有时也会猜错。那么,您如何纠正它呢?

您可能会发现,您不想所有的对象属性都变成表单字段;例如,您可能有一些私有属性是由您的表单模型内部使用的,或者您可能只想按不同的顺序排列字段,而不是在接口中排列属性。

要覆盖表单字段列表,实现您表单的可选-fields方法

- (NSArray *)fields
{
    return @[@"field1", @"field2", @"field3"];
}

字段方法应返回字符串、字典或它们的混合数组。在示例中,我们返回的是字符串;这些映射到表单对象的属性名称。如果您返回这种类型的名称数组,这些字段将替换自动生成的字段列表。

每次将表单重新分配给表单控制器时,都会再次调用-fields方法。这意味着您可以根据应用程序逻辑动态生成字段。例如,您可以基于其他属性显示或隐藏某些字段。

除了忽略和重新排列字段外,您可能还想覆盖它们的属性。有两种方法可以做到这一点:一种方法是在表单对象中添加一个方法,例如 -(NSDictionaryjekte_name]Field;,其中 name 是与字段相关的属性。该方法返回您想覆盖的属性字典(详见下文表单字段属性)。例如,如果我们想覆盖电子邮件字段的标题,我们可以这样做

- (NSDictionary *)emailField
{
    return @{FXFormFieldTitle: @"Email Address"};
}

另一种方法是返回字符串数组中的字典,而不是字符串。如果您这样做,您必须包括FXFormFieldKey,这样FXForms才知道您正在覆盖哪个字段

- (NSArray *)fields
{
    return @[
             @{FXFormFieldKey: @"email", FXFormFieldTitle: @"Email Address"},
             ...other fields...
            ];
}

这两种方法等价。

如果您想添加额外的虚拟表单字段(例如按钮或标签),这些字段与您表单类上的任何属性都不相对应,您可以通过实现-fields方法来做到。但如果你对默认字段满意,只想在最后添加一些额外的字段,你可以改用覆盖-extraFields方法,它的工作方式相同,但保留从表单类推断的默认字段

- (NSArray *)extraFields
{
    return @[
             @{FXFormFieldTitle: @"Extra Field"},
            ];
}

同样,如果您只想在表单中显示表单对象属性的一个子集,但不希望因为排除几个字段而在-fields方法中列出所有想要保留的属性,您可以使用-excludedFields方法来指定您不想包括的属性名称。

- (NSArray *)excludedFields
{
    return @[
             @"someProperty",
             @"someOtherProperty",
            ];
}

字段分组

您可能希望将表单字段分组到不同的部分,以便于使用。FXForms 使用非常简单的方式处理分组 - 您只需向任何字段添加 FXFormFieldHeaderFXFormFieldFooter 属性,它就会在那个点开始/结束该部分。

以下示例中,我们有四个字段,我们已将它们分成了两组,每组都有一个标题

- (NSArray *)fields
{
    return @[
             @{FXFormFieldKey: @"field1", FXFormFieldHeader: @"Section 1"},
             @"field2",
             @{FXFormFieldKey: @"field3", FXFormFieldHeader: @"Section 2"},
             @"field4",
            ];
}

或者,由于我们没有重写任何其他字段属性,我们可以通过以下方法更清洁地进行此操作

- (NSDictionary *)field1Field
{
    return @{FXFormFieldHeader: @"Section 1"};
}

- (NSDictionary *)field3Field
{
    return @{FXFormFieldHeader: @"Section 2"};
}

字段属性

您可以设置的表单字段属性列表如下。其中大部分都有合理的默认值自动设置。注意,这些常量的字符串值在接口中声明 - 您可以假设这些常量的字符串值在未来的版本中不会更改,并且您可以安全地在(例如)用于配置表单的 plist 中使用这些值。

static NSString *const FXFormFieldKey = @"key";

这是表单对象的关联属性的名称。如果您的字段没有实际的属性支持,这可能是指用于填充字段值的获取器方法的名称。也有可能拥有完全虚拟的字段(如按钮),它们根本没有任何键。

static NSString *const FXFormFieldType = @"type";

这是字段类型,它用于决定字段如何在表中显示。该类型用于确定要用于表示字段的单元格类型,但它也可以用于配置单元格(单个单元格类可能支持多种字段类型)。该类型会自动从字段属性声明中推断出,但也可能被覆盖。支持的类型在下文中列出,但您也可以提供任何字符串作为类型,并实现一个自定义表单单元格以显示和/或编辑它。

static NSString *const FXFormFieldClass = @"class";

这是表单值的类。对于原始类型,当通过 KVC 访问时(例如,对于数字值为 NSNumber,或对于结构体类型为 NSValue),这将用于装箱值。对于表单的所有属性,这将自动确定,因此您很少需要自己设置。对于通过使用 -fields-extraFields 方法自行添加的表单属性,有时需要显式指定此属性。一个很好的例子是,如果您正在添加视图控制器或子表单字段,类通常不能自动推断出。提供的值可以是 Class 对象或表示类名的字符串。

static NSString *const FXFormFieldCell = @"cell";

这是用于表示字段的单元格的类。默认情况下,此值未在字段级别指定;相反,FXFormController 维护一个从字段类型到单元格类的映射,这允许您在每个表单级别上覆盖默认单元格,而不是在每个字段级别上进行覆盖。如果您确实需要一个特殊的一次性单元格类型,您可以使用此属性来完成此操作。提供的值可以是 Class 对象或表示类名的字符串。

static NSString *const FXFormFieldTitle = @"title";

这是字段的显示标题。它自动从键生成,将 camelCase 转换为大写归一化格式,然后通过运行 NSLocalizedString() 宏进行本地化。这意味着您可以用此键覆盖标题,如果您更喜欢,也可以在字符串文件中这样做。

static NSString *const FXFormFieldPlaceholder = @"placeholder";

这是当字段值是nil或空时用于显示的占位符值。这通常是一个字符串,但也不必是,例如,它可以是日期字段的NSDate或图像字段的UIImage。当与选项或多选字段一起使用时,占位符将显示为选项列表中的第一个项目,并且可以用于将字段重置为nil/没有值。

static NSString *const FXFormFieldDefaultValue = @"default";

这是当字段值为nil时使用的默认值。在动态创建表单时,可以将默认值直接设置在字段数组中,而不是在表单的值中单独设置,这很有用。这也是确保字段值不会被用户设置为nil的一种方法。请注意,默认值与占位符值不同,因为它实际上将被存储在表单中。如果设置了默认值,则占位符将永远不会出现。默认值仅对对象类型可靠 - 因为零可能是整数或浮点属性的有意义值,所以它不会被默认值替换。

static NSString *const FXFormFieldOptions = @"options";

对于任何字段类型,您可以提供一组支持的值,这将覆盖标准字段,以选项列表的形式选择代替。选项可以是NSStrings、NSNumbers或任何其他对象类型。您可以提供FXFormFieldValueTransformer以控制选项值在列表中的显示方式。或者,如果您使用自定义对象作为值,您可以实现-(NSString *)fieldDescription;方法以控制其显示方式。有关更多详细信息,请参阅下面的表单字段选项。

static NSString *const FXFormFieldTemplate = @"template";

如果字段是NSArray或NSOrderedSet,FXForms允许用户添加、编辑和删除项目。默认情况下,FXForms假定集合中的值是FXFormFieldTypeText类型,但是您可以使用FXFormFieldTemplate字典来覆盖此设置。FXFormFieldTemplate字典包含与普通字段字典相同类型的大多数值,并且应用于描述集合中元素的属性。

static NSString *const FXFormFieldValueTransformer = @"valueTransformer";

有时,您想为字段显示的值可能与您存储的值不匹配。例如,您可能希望以特定格式显示日期,或将区域设置代码转换为可读形式。FXFormFieldValueTransformer属性允许您指定用于将字段值转换为字符串的转换块或NSValueTransformer。如果提供了值转换器,则将使用它而不是调用字段值对象的-fieldDescription方法。您可以提供NSValueTransformer的实例或子类名称。如果表单字段有选项数组,则值转换器也将用于控制选项在列表中的显示方式。FXFormFieldValueTransformer是可逆的,在这种情况下,它还会用于在将输入值存储到表单之前转换输入值。

static NSString *const FXFormFieldAction = @"action";

这是可选的字段将执行的操作。值可以是表示选择器名称的字符串,或是一个 блок,当字段被激活时将执行它。如果指定动作为一个选择器,则目标是通过从单元格向上遍历响应者链直到遇到响应该选择器的对象来确定。这意味着您可以选择在tabletview、其父视图、视图控制器、应用程序委托或窗口上实现此动作方法。如果您将表单作为另一个表单的子表单显示,您还可以在它们的父表单视图控制器中实现子表单的动作方法。

对于非交互式字段,当单元格被选中时,将调用操作;对于开关或文本字段等字段,当值更改时将触发操作。在使用选择器时,操作方法可以接受零个或一个参数。所提供的参数将是发送者,通常是表单字段单元格(一个符合UITableViewCell协议的 FXFormFieldCell),您可以通过它访问字段模型,并从该模型访问表单本身。

static NSString *const FXFormFieldSegue = @"segue";

这是一个当字段被点击时执行的UIStoryboardSegue。这可以是UIStoryboardSegue子类(或包含UIStoryboardSegue子类名称的字符串),UIStoryboardSegue子类的一个实例,或者表示附加到表单视图控制器的 segue 的标识符的字符串。请注意,在后一种情况下,segue 必须附加到与表单相同的控制器,否则在调用时将会崩溃。

如果 FXFormFieldSegue 属性是 segue 实例或标识符,当字段被点击时会调用它。如果它是 segue 子类,则会启动并使用这个 segue 来处理显示子表单或子控制器时的转换。

static NSString *const FXFormFieldHeader = @"header";

此属性提供可选的表头,在字段之前显示。值可以是字符串、UIView实例或子类(或包含UIView子类名称的字符串)。表头的高度将从视图推断出来,或者您可以使用 UITableViewDelegate 来覆盖它。默认情况下,它的值将根据子表单属性的名称自动推断。提供空字符串或NSNull值以创建不带标题的分隔区域。

static NSString *const FXFormFieldFooter = @"footer";

此属性提供可选的表尾字符串,在字段之后显示。值可以是字符串、UIView实例或子类(或包含UIView子类名称的字符串)。表尾的高度将从视图推断出来,或者您可以使用 UITableViewDelegate 来覆盖它。提供空字符串或NSNull值以创建不带表尾的分隔区域,或者完全省略FXFormFieldFooter键。

static NSString *const FXFormFieldInline = @"inline";

其值是另一个FXForm或提供了选项数组的字段通常将在新的FXFormViewController中显示,在点击字段时会将其推入导航堆栈。您可能希望将此类字段作为同一tableView中的行内字段显示。您可以通过将FXFormFieldInline属性设置为@YES来做到这一点。

static NSString *const FXFormFieldSortable = @"sortable";

类型为 NSArray 或 NSOrderedSet 的字段可选项显示排序控件,以便用户可以更改项目顺序。将 FXFormFieldSortable 属性设置为 YES 以启用此功能。

static NSString *const FXFormFieldViewController = @"controller";

某些类型的字段可能会在另一个视图控制器中显示,当选择字段时,该控制器将被推入导航堆栈。默认情况下,在字段级别上不指定此类;相反,FXFormController维护一个字段类型到控制器类的映射,这允许您在每份表单级别而不是每字段级别覆盖默认控制器,以显示给定的字段类型。如果您确实需要提供特殊的一次性控制器类型,FXFormFieldViewController 属性允许您在每字段级别指定要使用的控制器。FXFormViewController可以是UIViewController实例或类(或包含类名称的字符串)。指定的控制器必须符合FXFormFieldViewController协议。默认情况下,此类字段将使用FXFormViewController类来显示。

表单字段类型

static NSString *const FXFormFieldTypeDefault = @"default";

这是默认字段类型,如果无法确定特定类型则使用该类型。

static NSString *const FXFormFieldTypeLabel = @"label";

此类型可用于将字段视为非交互式/只读。将使用 -fieldDescription 方法将值转换为字符串以显示表单值。这映射到所有内置类型的标准 NSObject -description 方法,但您可以为您自己的自定义值类重写它。

static NSString *const FXFormFieldTypeText = @"text";

默认情况下,此字段类型将以带有默认自动更正的普通 UITextField 表示。

static NSString *const FXFormFieldTypeLongText = @"longtext";

此类型表示多行文本。默认情况下,此字段类型将以可扩展的 UITextView 表示。

static NSString *const FXFormFieldTypeURL = @"url";

类似于 FXFormFieldTypeText,但键盘类型为 UIKeyboardTypeURL,没有自动更正。

static NSString *const FXFormFieldTypeEmail = @"email";

类似于 FXFormFieldTypeText,但键盘类型为 UIKeyboardTypeEmailAddress,没有自动更正。

static NSString *const FXFormFieldTypePassword = @"password";

类似于 FXFormFieldTypeText,但启用了安全文本输入,没有自动更正。

static NSString *const FXFormFieldTypeNumber = @"number";

类似于 FXFormFieldTypeText,但具有数字键盘,且输入限制为有效数字。

static NSString *const FXFormFieldTypeInteger = @"integer";

类似于 FXFormFieldTypeNumber,但限制为整数输入。

static NSString *const FXFormFieldTypeUnsigned = @"unsigned";

类似于 FXFormFieldTypeInteger,但用于无符号值。默认使用数字键盘。

static NSString *const FXFormFieldTypeFloat = @"float";

类似于 FXFormFieldTypeNumber,但表示值是原生的(不可为 null)。

static NSString *const FXFormFieldTypeBoolean = @"boolean";

布尔值,默认使用 UISwitch 控件设置。

static NSString *const FXFormFieldTypeOption = @"option";

类似于 FXFormFieldTypeBoolean,但此类型用于切换选项,默认创建复选框控件而不是开关。

static NSString *const FXFormFieldTypeDate = @"date";

日期值,使用 UIDatePicker 选择。

static NSString *const FXFormFieldTypeTime = @"time";

时间值,使用 UIDatePicker 选择。

static NSString *const FXFormFieldTypeDateTime = @"datetime";

日期和时间,使用 UIDatePicker 选择。

static NSString *const FXFormFieldTypeImage = @"image"

图片,使用 UIImagePickerController 选择。

表单字段选项

为表单字段提供选项数组时,字段输入将显示为可勾选的选项列表。如何将此选项列表转换为表单值取决于字段类型。

如果字段类型与选项数组中的值匹配,选择选项将直接设置选定值,但这可能不是您想要的。例如,如果您有一个字符串列表,您可能对选定的索引比对值的兴趣更大(该值可能已被本地化和格式化以便人类消费,而不是机器解释)。如果字段类型是数字,并且选项值不是数字,则假定字段值应设置为所选项目的 索引,而不是值。

如果字段是集合类型(例如 NSArray、NSSet 等),则表单允许用户选择多个选项,而不是一个。根据属性的类别处理集合,如下所示:如果您使用 NSArrayNSSetNSOrderedSet,则选定的值将直接存储在集合中;如果您使用 NSIndexSet,则存储值的索引;如果您使用 NSDictionary,则存储值及其索引。对于有序集合类型,保证选定的值顺序与选项数组中的顺序匹配。

多选字段还可以与 NS_OPTIONS 风格的位字段枚举值一起使用。只需将整数或枚举作为属性类型,然后指定字段类型为 FXFormFieldTypeBitfield。然后,您可以通过使用 NSNumber 值指定选项中的显式位数,或者让 FXForms 从选项索引推断位值。

注意:在运行时,FXForms 无法访问您枚举中定义的实际值,因此选定的值仅由 FXFormFieldOptions 值的索引值确定。如果您的枚举值不是顺序的,或者不以零开始,则索引不会与选项索引匹配。为了定义具有非顺序值的枚举选项,您可以指定显式的数值选项,并使用 FXFormFieldValueTransformer 来显示可读的标签,如下所示

typedef NS_ENUM(NSInteger, Gender)
{
    GenderMale = 10,
    GenderFemale = 15,
    GenderOther = -1
};

- (NSDictionary *)genderField
{
    return @{FXFormFieldOptions: @[@(GenderMale), @(GenderFemale), @(GenderOther)],
             FXFormFieldValueTransformer: ^(id input) {
             return @{@(GenderMale): @"Male",
                      @(GenderFemale): @"Female",
                      @(GenderOther): @"Other"}[input];
    }};
}

单元格配置

如果您想要调整字段的某些属性,而不需要子类化它们,实际上通过在字段字典中添加额外的值,只需通过keyPath设置任何单元格属性。例如,此代码将电子邮件字段的文本标签变为红色

- (NSDictionary *)emailField
{
    return @{@"textLabel.color": [UIColor redColor]};
}

此代码将禁用名称字段的自动首字母大写

- (NSDictionary *)nameField
{
    return @{@"textField.autocapitalizationType": @(UITextAutocapitalizationTypeNone)};
}

在FXForm控制器中不会回收单元格,因此您无需担心清理以这种方式设置的任何属性。但是请注意,过度使用此类“字符串化类型”代码可能会有风险,因为错误在编译时无法捕获。对于重型定制,最好创建单元格子类并在-setField:方法中重写属性。

自定义单元格

FXForms为所有支持的字段提供默认的单元格实现。您可能需要为自定义字段类型提供额外的单元格类,甚至可以用您应用程序的自定义版本替换所有的FXForm单元格。

对于单元格,可以有两级定制。最简单的方法是从现有的FXFormCell类中派生出一个,所有这些类都继承自FXFormBaseCell。这些单元格类包含了处理各种不同字段类型的很多逻辑,同时也暴露了视图和控制,以便于自定义。

当派生自现有的单元格类型时,您可以重写setUpupdatedidSelectWithTableView:controller:方法(有选择地调用[super ...]以继承原始单元格的行为)。setUp方法将在单元格创建时只调用一次,而update方法将在字段值更新时每次调用。

如果您已经有了一个基本单元格类,并且不想基于FXFormBaseCell创建单元格,您可以通过从UITableViewCell派生并采用FXFormFieldCell协议从头开始创建一个FXForms兼容的单元格。

您的自定义单元格必须有一个类型为FXFormField的属性。这是一个用于封装字段属性的包装类,也提供了一种设置和获取相关表单值的方式(通过field.value虚拟属性)。请注意,您不能直接实例化FXFormField对象,但是可以通过FXFormController上的方法访问和枚举它们。

创建自定义单元格后,可以这样使用

  • 如果您的单元格仅用于少数几个特定的字段,您可以使用FXFormFieldCell属性将它用于特定的表单字段
  • 如果您的单元格旨在处理特定的字段类型(或类型),您可以通过FXFormController的-registerCellClass:forFieldType:方法告诉表单控制器使用您的自定义单元格类
  • 如果您的单元格旨在处理特定的字段值类(或子类),您可以通过FXFormController的-registerCellClass:forFieldClass:方法告诉表单控制器使用您的自定义单元格类
  • 如果您想完全用您自己的类替换所有单元格,使用FXFormController-registerDefaultFieldCellClass:方法。这将为所有字段类型替换所有默认单元格关联到您的新单元格类。然后,您可以使用-registerCellClass:forFieldType:添加特定类型的额外单元格类。

Swift 兼容性

FXForms完全与Swift兼容,但有以下注意事项

  • 您的表单对象必须从NSObject继承,或使用@objc限定符声明。
  • 对于集合字段,必须使用NSArrayNSDictionaryNSOrderedSet等。Swift的强类型集合将无法正常工作。
  • 如果您的表单对象在主应用程序以外的模块中声明,FXForm的字段值类推断可能无法正确工作,在这种情况下,您可以通过在每个不正常工作的字段上添加以下方法来显式指定字段类
func fieldThatDoesntWorkField() -> NSDictionary {
    return [FXFormFieldClass: fieldThatDoesntWork.dynamicType]
}

版本更新

版本 1.2.14

  • 修复了键盘显示/隐藏问题
  • 为了与Swift兼容性,已从 nib 名称中移除命名空间
  • 修复了在 iPad 横屏模式下的过大边距
  • 设置了文本标签的无障碍值
  • 修复了在点击取消时打开图像选择器的问题

版本 1.2.13

  • 在 FXFormBaseCell 上公开了 nextCell 属性
  • 修复了长 UITextView 在滚到光标位置而不是.TextView 的底部
  • 确保当键盘关闭时,之前的 tableView contentInsets 被恢复。
  • 使自定义单元格配置向下级联到选项视图中
  • 修复了与 BaseModel 一起使用时崩溃的 bug
  • 修复了在 Xcode 7 测试版中出现的警告(嗯,大多数已抑制)

版本 1.2.12

  • 模板字段的自定义标题不再在每项字段中显示,仅用于“添加项”按钮标题。
  • 修复了与使用标量默认值有关的其他崩溃问题
  • 反向值转换应现在可以正确工作

版本 1.2.11

  • 集合字段的字段描述现在尊重 FXPropertyValueTransformer
  • 将标量值用作集合类型字段的默认值现在可以透明处理

版本 1.2.10

  • 修复了在 iPad 上显示照片选择器时的崩溃问题

版本 1.2.9

  • 使用 nib 定义的单元格现在会从 nib 推断其高度(除非已经显示覆盖)
  • 选项选择器现在可以通过再次点击字段来关闭,就像日期选择器一样

版本 1.2.8

  • 修复了具有 segue 属性的字段类型推断不正确的问题
  • 日期选择器现在可以再次点击日期字段来关闭

版本 1.2.7

  • 修复了按钮类型字段(有一个操作但没有可编辑值的字段)无法正确推断的问题

版本 1.2.6

  • 改进了 valueClass 推断,特别是对于模板字段
  • FXFormImagePickerCell 现在让您选择相机或相册

版本 1.2.5

  • 修复了表单部分有页脚但没有页头时的崩溃问题

版本 1.2.4

  • 对于使用 8.1 SDK 构建的构建,iOS7 上不再显示 hashdescription 等。
  • FXFormViewController 现在可以是视图控制器类或实例

版本 1.2.3

  • 添加了一个修正,当使用 Swift 时,允许 FXForm 自动推断表单和控制器的类型,就像与 Objective-C 一样
  • 如果在没有嵌入在 UINavigationController 内部时尝试显示子表单,则会抛出异常

版本 1.2.2

  • 修复了子表单将被新实例覆盖的 bug

版本 1.2.1

  • 修复了即使没有设置页脚文本,也会错误显示表格页脚间距的问题
  • 修复了与使用默认值有关的崩溃问题
  • 对小范围的 Swift 兼容性进行了修正
  • 添加了 Swift 示例项目

版本 1.2

  • 现在可以编辑如 NSArray、NSSet、NSOrderedSet 等集合字段类型,通过添加、删除和排列项
  • 公开了 FXFormsBaseCell 的 setUp 和 update 方法,以便于子类化
  • 添加了 FXFormsDefaultCell 以实现标准行为(以简化子类化)
  • 添加了 FXFormOptionSegmentsCell 用于创建应用于集合的模板值
  • 添加了 FXFormFieldSegue 属性,用于指定在点击字段时执行 segue
  • 添加了 FXFormFieldTypePhone 字段类型
  • 添加了 FXFormFieldTypeUnsigned 字段类型
  • 添加了 FXFormOptionSegmentsCell 类
  • 添加了 FXFormFieldDefault 以指定表单字段的默认值
  • 添加了根据字段值类和类型注册单元格和控制器类的能力
  • 修复了步进器字段中值更改后标签无法缩放的问题
  • 修复了FXImagePickerCell中图像预览显示不正确宽度的bug
  • 修复了NSURL字段的处理
  • 动态字段的类型推断现在工作得更好
  • 添加了动态字段示例(从JSON文件加载表单字段描述)
  • 向FXFormController添加了indexPathForField:方法
  • FXForm的tableView现在始终处于编辑模式 - 这可能会影响自定义单元格的布局
  • 指定的FXFormFieldValueTransformer对象现在可逆
  • 文本字段表单值现在在编辑期间实时更新
  • 为表单添加了-excludedFields方法以排除某些字段
  • 现在忽略iOS 8中引入的标准@properties,如hashdescription
  • 现在可以使用UIView类或实例作为FXFormFieldHeader/Footer的值

版本1.1.6

  • 带有数值的选项字段现在正确显示
  • 当选项字段更新时将调用action块
  • 当点击子表单字段单元格时不再调用action块
  • 修复了使用占位符值与选项字段一起使用时的崩溃问题
  • 添加了FXFormFieldTypeFloat
  • 添加了相关字段示例

版本1.1.5

  • 没有键的虚拟字段不再在表单对象为NSManagedObject子类时崩溃

版本1.1.4

  • FXForms现在正确将所有控制代理和数据源置为nil,以防止表单关闭时崩溃
  • FXFormImagePickerCell的图像不再使用不正确的对齐方式绘制
  • FXFormTextViewCell现在可以在为空时显示占位符文本

版本1.1.3

  • 使用Field方法设置表单属性的设置不再被默认值覆盖
  • 只有在视图控制器不是UITableViewController时才能调整内边距/偏移
  • 现在应该更容易使用nib文件布局单元格子类而不会丢失标准功能
  • 使用FXFormFieldTypeLabel现在更加一致

版本1.1.2

  • 修复了转发scrollViewWillBeginDragging事件错误的问题
  • 现在正确处理类型为FXFormFieldTypeBitfield的字段(在1.1.1中损坏)
  • 现在可以创建不继承所有标准样式逻辑的自定义单元格类
  • 添加了使用nib文件创建自定义表单单元格子类的示例(CustomButtonExample)
  • FXForms现在不会尝试自动实例化nil的NSManagedObject(这会造成之前的崩溃)

版本1.1.1

  • 修复了索引选项字段的bug
  • 当在字段之间使用Tab键导航时,FXFormOptionPickerCell选择的索引现在正确设置

版本1.1

  • 添加了对多选选项字段的支持 - 只需为选项字段使用数组类型的集合,如NSArray、NSSet或NSIndexSet
  • 为NS_OPTIONS类型的多选枚举值添加了FXFormFieldTypeBitfield
  • 添加了FXFormFieldOptionPickerCell作为显示选项字段的另一种方式(不支持多选)
  • 嵌套的表单现在父级表单视图控制器以及向上到应用程序代理传播表单操作
  • 向FXFormController添加了parentFormController属性
  • FXFormField的action属性现在是一个块而不是选择器(可以在形式字典中指定)
  • 添加了FXFormFieldPlaceholder值,用于在值为nil/空时显示
  • 在下一个单元格可以接受FirstResponder的情况下,键盘将显示"下一个"按钮
  • 添加了FXFormFieldTypeImage和FXFormImagePickerCell
  • 添加了FXFormFieldTypeLongText以显示多行文本
  • 添加了FXFormFieldValueTransformer以适应字段值以在显示时使用
  • 现在可以通过重写setValue:forKey:来设置属性创建完全虚拟的表单对象
  • 为指定自定义表单字段视图控制器添加了FXFormFieldViewController属性
  • 添加了一些额外的示例项目以展示新功能
  • 按钮类型字段(仅包含操作且没有键的字段)默认文本现在居中
  • 现在可以通过在字段配置中使用“style”键路径来覆盖UITableViewCellStyle,而无需子类化

版本 1.0.2

  • 修复尝试在 FXFormTextFieldCell 上设置 UITextInputTraits 属性时发生崩溃的问题
  • 修复使用字符串属性时数字字段类型可能造成的潜在崩溃问题

版本 1.0.1

  • 子表单 FXFormController 实例现在正确继承父控制器中注册的单元格
  • 与关联操作相关的 FXFormFieldOption 类型的字段现在在触发操作前仍将被切换

版本 1.0

  • 首次发布