FXForms 是一个 Objective-C 库,可轻松在 iOS 上创建基于表格的表单。它非常适合设置页面或数据录入任务。
与其他解决方案不同,FXForms 直接与您提供的强类型数据模型协同工作(而不是字典或复杂的 dataSource 协议),并尽可能从您的模型中推断信息,以避免重复类型信息的繁琐过程。
注意:“支持”意味着库已与该版本进行过测试。“兼容”意味着库应在此 iOS 版本上运行(即它不依赖于任何不可用的 SDK 功能),但不再对此版本进行兼容性测试,可能需要调整或错误修复才能正确运行。
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 真的非常智能;比您想象的要聪明得多
UISwitch
,电子邮件字段将自动拥有 UIKeyboardTypeEmailAddress
类型的键盘,而密码字段将自动启用 secureTextEntry
。FXForm
协议的属性)或视图控制器(例如条款和条件页面),如果它们为 nil,它们将自动实例化 - 无需设置默认值。所有默认行为都是通过使用 Objective-C 的运行时 API 检查属性类型和名称推断出来的,但如果您愿意,也可以覆盖它们 - 这将在稍后的“调整表单行为”中介绍。
要在视图控制器中显示您的表单,您有两个选择:《code>FXForms提供了一个名为 FXFormViewController
的 UIViewController
子类,设计得尽可能简单。要设置 FXFormViewController
,只需像平常一样创建它,并按以下方式设置您的表单
FXFormViewController *controller = [[FXFormViewController alloc] init];
controller.formController.form = [[MyForm alloc] init];
然后您可以像任何普通视图控制器一样显示表单控制器。《code>FXFormViewController 包含一个 UITableView
,它将自动创建所需的表格视图。如果您更喜欢的话,您可以将自己的 UITableView
分配给 tableView
属性并使用它。您甚至可以初始化一个包含创建 UITableView
的 nib 文件的 FXFormViewController
。
就像常规的 UIViewController
或 UITableViewController
一样,《code>FXFormViewController 是可子类化的。在大多数情况下,您可能会想要子类化 FXFormViewController
以添加您自己的表单设置逻辑和操作处理器。
将 FXFormViewController
(或子类)放入 UINavigationController
中是一个好主意。这不是强制性的,但如果表单包含子表单,这些子表单将被推向其 navigateController,如果没有,表单则不会显示。
与 UITableViewController
类似,《code>FXFormViewController 通常将 tableView 作为控制器的主视图。与 UITableViewController
不同的是,它 不必 是的 - 如果您更喜欢,您可以做出您的 tableView 成为主要视图的子视图。
与 UITableViewController
类似,《code>FXFormViewController 实现了 UITableViewDelegate
协议,因此,如果您子类化它,您可以覆盖 UITableViewDelegate
和 UIScrollViewDelegate
方法以实现自定义行为。《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 使用非常简单的方式处理分组 - 您只需向任何字段添加 FXFormFieldHeader
或 FXFormFieldFooter
属性,它就会在那个点开始/结束该部分。
以下示例中,我们有四个字段,我们已将它们分成了两组,每组都有一个标题
- (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 等),则表单允许用户选择多个选项,而不是一个。根据属性的类别处理集合,如下所示:如果您使用 NSArray
、NSSet
和 NSOrderedSet
,则选定的值将直接存储在集合中;如果您使用 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
。这些单元格类包含了处理各种不同字段类型的很多逻辑,同时也暴露了视图和控制,以便于自定义。
当派生自现有的单元格类型时,您可以重写setUp
、update
和didSelectWithTableView:controller:
方法(有选择地调用[super ...]以继承原始单元格的行为)。setUp
方法将在单元格创建时只调用一次,而update
方法将在字段值更新时每次调用。
如果您已经有了一个基本单元格类,并且不想基于FXFormBaseCell
创建单元格,您可以通过从UITableViewCell
派生并采用FXFormFieldCell
协议从头开始创建一个FXForms兼容的单元格。
您的自定义单元格必须有一个类型为FXFormField
的属性。这是一个用于封装字段属性的包装类,也提供了一种设置和获取相关表单值的方式(通过field.value
虚拟属性)。请注意,您不能直接实例化FXFormField
对象,但是可以通过FXFormController
上的方法访问和枚举它们。
创建自定义单元格后,可以这样使用
FXFormFieldCell
属性将它用于特定的表单字段-registerCellClass:forFieldType:
方法告诉表单控制器使用您的自定义单元格类-registerCellClass:forFieldClass:
方法告诉表单控制器使用您的自定义单元格类FXFormController
的-registerDefaultFieldCellClass:
方法。这将为所有字段类型替换所有默认单元格关联到您的新单元格类。然后,您可以使用-registerCellClass:forFieldType:
添加特定类型的额外单元格类。FXForms完全与Swift兼容,但有以下注意事项
NSObject
继承,或使用@objc
限定符声明。NSArray
、NSDictionary
、NSOrderedSet
等。Swift的强类型集合将无法正常工作。func fieldThatDoesntWorkField() -> NSDictionary {
return [FXFormFieldClass: fieldThatDoesntWork.dynamicType]
}
版本 1.2.14
版本 1.2.13
nextCell
属性版本 1.2.12
版本 1.2.11
版本 1.2.10
版本 1.2.9
版本 1.2.8
版本 1.2.7
版本 1.2.6
valueClass
推断,特别是对于模板字段FXFormImagePickerCell
现在让您选择相机或相册版本 1.2.5
版本 1.2.4
hash
、description
等。FXFormViewController
现在可以是视图控制器类或实例版本 1.2.3
版本 1.2.2
版本 1.2.1
版本 1.2
hash
和description
版本1.1.6
版本1.1.5
版本1.1.4
版本1.1.3
版本1.1.2
版本1.1.1
版本1.1
版本 1.0.2
版本 1.0.1
版本 1.0