MYSForms 0.1.3

MYSForms 0.1.3

测试已测试
Lang语言 Obj-CObjective C
许可证 MIT
Released最后发布2015年8月

Adam Kirk维护。



MYSForms 0.1.3

iOS上的简单表单。

用于Firehose Chat iOS应用程序中。

内容

安装

要尝试一下,使用--recursive克隆此库,并打开演示应用程序,展示了几种不同类型的表单和表单元素。

需求

iOS 7+

简介

MYSForms允许您轻松地在iOS上构建表单进行展示。表单绑定到模型,可以是任何对象、字典,甚至是[NSUserDefaults standardUserDefaults]。您可以验证您的表单,显示错误/成功/加载消息等。

MYSForms基于UICollectionViewController。这意味着它们非常灵活且可定制。这也意味着在使用应用程序时它们极其容易使用。您只需创建一个MYSFormViewController实例,进行配置,然后再像任何其他视图控制器一样展示即可。或者,你可以继承MYSFormViewController并展示您的子类。

要配置表单,您只需向其中添加MYSFormElement对象即可。就是这样。

使用

表单

表单是

  1. 绑定到模型。
  2. 一个表单元素的数组,每个元素都绑定到模型上的键路径。当用户更新表单时,模型也随之更新。当模型发生变化时,表单自动反映模型的数据。

创建表单有两种方式

  1. 创建一个MYSFormViewController实例并向其中添加表单元素。
  2. 创建MYSFormViewController的子类,并覆盖configureForm方法,在那里添加表单元素。

阅读MYSFormViewController的API文档

Storyboard

如果您在使用故事板,使用继承方法更为合适。只需将一个 UICollectionViewController 拖拽到您的故事板上,并将视图控制器的类设置为您的自定义子类。当应用切换到该场景(派生自 MYSFormViewController)时,表单将会出现并自动执行。

表单元素

表单是一个包含 MYSFormElement 子类对象数组的 MYSFormViewController。每个 MYSFormElement 子类代表不同的表单元素,如标题、描述性文本、文本框、文本视图、选择器、切换按钮、图片选择器等。

MYSForms提供大量可以使用的 MYSFormElement 子类,您也可以创建自己的或进一步派生现有的类来调整它们的样式和行为。

验证

验证是您可以添加到表单元素中的对象,以确保这些元素的值有效。如果值无效,它会在表单元素旁边自动显示验证错误,解释问题,用户可以据此进行修正。MYSForms提供一些标准的验证类,如确保值非空或确保值符合特定格式。验证对象是 MYSFormValidation 的子类。

值转换器

由于每个可编辑的表单元素可能会绑定到模型上的一个属性,您可能想给元素添加一个转换器,以便当从模型读取模型值时,它可以转换为适用于视觉显示的类型。同样,当用户更改值时,您的转换器可以将视觉形式转换为模型期望的类型。转换器是 NSValueTransformer 的子类。

示例

创建表单

假设我们想通过创建 MYSFormViewController 的实例并向其中添加一些表单元素来创建一个表单

// create an instance of MYSFormViewController
MYSFormViewController *formViewController = [MYSFormViewController new];

// setting the model
formViewController.model = self.fakeUser;

// add a header element
MYSFormLabelElement *headline = [MYSFormLabelElement labelElementWithText:@"Log In"];
[formViewController addFormElement:headline];

// add a text field for the user to type in an email
MYSFormTextFieldElement *emailField = [MYSFormTextFieldElement textFieldElementWithLabel:@"E-mail" modelKeyPath:@"email"];
emailField.keyboardType = UIKeyboardTypeEmailAddress;
[formViewController addFormElement:emailField];

// push the form onto the navigation stack and that's it!
[self.navigationController pushViewController:formViewController animated:YES];

第二种,更稳健的方法,您可以像这样继承 MYSFormViewController

MYSSignUpFormViewController.h

#import "MYSForms.h"

@interface MYSSignUpFormViewController : MYSFormViewController
@end

MYSSignUpFormViewController.m

#import "MYSSignUpFormViewController.h"
#import "MYSExampleUser.h"


@implementation MYSSignUpFormViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.model = [MYSExampleUser new];
}

- (void)configureForm
{
    [super configureForm];

    [self addFormElement:[MYSFormLabelElement labelElementWithText:@"Sign Up"]];

    [self addFormElement:[MYSFormLabelElement labelElementWithText:
                          @"Example of a subclassed form view controller where a blank model is created in its viewDidLoad."]];

    [self addFormElement:[MYSFormTextFieldElement textFieldElementWithLabel:@"First Name" modelKeyPath:@"firstName"]];

    [self addFormElement:[MYSFormTextFieldElement textFieldElementWithLabel:@"Last Name" modelKeyPath:@"lastName"]];

    MYSFormTextFieldElement *emailField = [MYSFormTextFieldElement textFieldElementWithLabel:@"E-mail" modelKeyPath:@"email"];
    emailField.keyboardType = UIKeyboardTypeEmailAddress;
    [self addFormElement:emailField];

    MYSFormTextFieldElement *passwordField = [MYSFormTextFieldElement textFieldElementWithLabel:@"Password" modelKeyPath:@"password"];
    passwordField.secure = YES;
    [self addFormElement:passwordField];
}

添加验证

一个带验证的电子邮件字段的示例

MYSFormTextFieldElement *emailField = [MYSFormTextFieldElement textFieldElementWithLabel:@"E-mail" modelKeyPath:@"email"];
emailField.keyboardType = UIKeyboardTypeEmailAddress;
[emailField addFormValidation:[MYSFormPresenceValidation new]];
[emailField addFormValidation:[MYSFormRegexValidation regexValidationWithName:MYSFormRegexValidationPatternEmail]];
[self addFormElement:emailField];

使用值转换器

在这里我们添加了一个当点击时显示 UIPickerView 的表单元素。使用值转换器将模型的 NSNumber 值转换为 NSString 以供选择器元素显示。

MYSFormPickerElement *pickerElement = [MYSFormPickerElement pickerElementWithLabel:@"Age" modelKeyPath:@"yearsOld"];
pickerElement.valueTransformer = [MYSFormStringFromNumberValueTransformer new];
for (NSInteger i = 0; i < 120; i++) {
    [pickerElement addValue:@(i)];
}
[self addFormElement:pickerElement];

显示错误、成功和加载消息

在特定的表单元素下方显示一个错误消息

[self addFormElement:[MYSFormLabelAndButtonElement buttonElementWithLabel:@"A label" title:@"And button" block:^(MYSFormButtonElement *element) {
    [self showErrorMessage:@"An error message." belowElement:element duration:3 completion:nil];
}]];

在特定的表单元素下方显示一个成功消息

[self addFormElement:[MYSFormButtonElement buttonElementWithTitle:@"Button" block:^(MYSFormElement *element) {
    [self showSuccessMessage:@"A success message." belowElement:element duration:3 completion:nil];
}]];

在特定的表单元素上方显示一个加载消息

[self addFormElement:[MYSFormButtonElement buttonElementWithTitle:@"Show Loading Specific" block:^(MYSFormElement *element) {
    [self showLoadingMessage:@"Loading for a specific form element." aboveElement:self.firstNameElement completion:nil];
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(4 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self hideLoadingAboveElement:self.firstNameElement completion:nil];
    });
}]];

自定义

有两种方式来自定义表单

  1. 使用 MYSFormTheme
  2. 派生元素/单元格并替换 xibs。

方法 1:MYSFormTheme

您可以为 MYSFormTheme 创建一个新的实例,调整该对象的属性,然后将其分配给任何 MYSFormElement。如果您在主题上自定义了标签字体/颜色属性,那么赋予该主题的任何元素的标签都将应用这些自定义。

您还可以将主题分配给整个表单,该主题随后将传递到所有元素中。元素主题上设置的属性将覆盖传递给元素的表单主题。例如,如果您在两个不同的主题上设置了 tintColor 属性,将一个分配给表单,另一个分配给一个元素,则该元素将使用直接分配给它的主题上的 tintColor

以下是一个设置表单主题上某些属性(在 self.theme 上设置)和分配给一个元素的主题的示例

- (void)configureForm
{
    [super configureForm];

    // set a form-wide theme
    self.theme = [MYSFormTheme new];
    self.theme.buttonStyle = @(MYSFormButtonStyleFilled);
    self.theme.labelFont = [UIFont fontWithName:@"Avenir" size:12];
    self.theme.inputTextFont = [UIFont fontWithName:@"Noteworthy" size:14];

    MYSFormLabelElement *headlineElement = [MYSFormLabelElement labelElementWithText:@"A Headline"];
    headlineElement.theme = [MYSFormTheme formThemeWithLabelFont:[UIFont fontWithName:@"Zapfino" size:26]];
    [self addFormElement:headlineElement];
}

方法 2

根据您想要多疯狂,您可以继承整个元素、仅继承其单元格或仅替换其 xib 以您的自定义版本。如果您只想改变单元格的自动布局方式或移动元素单元格中的视图,仅替换 xib 以您的自定义版本即可。如果您想自定义动画、行为或基于内容计算高度,那么您将想要继承元素的单元格。如果您继承了一个单元格,您还必须用您自己的替换 xib。以下介绍如何继承一个元素的单元格

假设您想自定义表头元素的外观。您可以像这样继承 MYSFormHeadlineCell.h

FCIFormHeaderCell.h

#import <MYSForms.h>

@interface FCIFormHeaderCell : MYSFormHeadlineCell
@end

FCIFormHeaderCell.m

#import "FCIFormHeaderCell.h"

@implementation FCIFormHeaderCell

+ (CGSize)sizeRequiredForElement:(MYSFormElement *)element width:(CGFloat)width
{
    return CGSizeMake(width, 100);
}

@end

然后,在您实际提供 UI 的地方

FCIFormHeaderCell.xib

Demonstration of hooking up outlets to superclass

技巧是确保您的 xib 中视图的 outlets 连接到 MYSFormHeadlineCell 超类的属性。

YourFormViewController.m

- (void)configureForm
{
    [super configureForm];

    MYSFormHeadlineElement *headlineElement = [labelElementWithText labelElementWithText:@"Sign Up"];
    headlineElement.cellClass = [FCIFormHeaderCell class];
    [self addFormElement:headlineElement];
}

就是这样。为了总结

  1. 创建一个您想要自定义的单元格的子类。在这个例子中,我们创建了 FCIFormHeaderCell 类,该类继承自 MYSFormHeadlineCell
  2. 创建一个与您的自定义单元格子类名称匹配的 xib 文件。
  3. 在这个 xib 中自定义单元格的外观,并确保所有 iTunes 连接到。
  4. 确保单元格的重用标识符为您的自定义类名称。
  5. 在配置表单时,确保告诉元素使用您的自定义单元格类/xib。

截图

登录表单和注册表单

Basic Example Screenshot Sign up form example

验证错误和加载消息

Example of validation errors Example of a loading message

其他元素示例

Example catalog elements Example of misc form elements

附加信息

还有一个名为 MYSFormSlideViewControllerMYSFormViewController 子类,它是 MYSForms 的一部分,当显示时,将从底部滑出表单。

如果您使用 MYSCollectionView 并使用 MYSCollectionViewSpringyLayout,您将获得一种有趣的弹簧效果,在表单中的元素之间。

贡献

使用 --recursive 克隆仓库,因为有一些重要的子模块需要包含在内。

在提交 pull 请求之前,请更新并运行测试。谢谢。

作者

Adam Kirk (@atomkirk)

查看Firehose Chat,并将免费聊天框添加到您的网站,以便与访客进行聊天。当访客想要聊天时,即使您处于离线状态,您也会收到推送通知。您可以通过iOS应用或Mac应用立即进行回复。