Git Product home page Git Product logo

fxforms's Introduction


WARNING: THIS PROJECT IS DEPRECATED

It will not receive any future updates or bug fixes. If you are using it, please migrate to another solution.


Purpose

FXForms is an Objective-C library for easily creating table-based forms on iOS. It is ideal for settings pages or data-entry tasks.

Unlike other solutions, FXForms works directly with strongly-typed data models that you supply (instead of dictionaries or complicated dataSource protocols), and infers as much information as possible from your models using introspection, to avoid the need for tedious duplication of type information.

Screenshot of BasicExample

Supported iOS & SDK Versions

  • Supported build target - iOS 9.0 (Xcode 7.0, Apple LLVM compiler 7.0)
  • Earliest supported deployment target - iOS 7.0
  • Earliest compatible deployment target - iOS 5.0

NOTE: 'Supported' means that the library has been tested with this version. 'Compatible' means that the library should work on this iOS version (i.e. it doesn't rely on any unavailable SDK features) but is no longer being tested for compatibility and may require tweaking or bug fixes to run correctly.

ARC Compatibility

FXForms requires ARC. If you wish to use FXForms in a non-ARC project, just add the -fobjc-arc compiler flag to the FXForms.m class. To do this, go to the Build Phases tab in your target settings, open the Compile Sources group, double-click FXForms.m in the list and type -fobjc-arc into the popover.

If you wish to convert your whole project to ARC, comment out the #error line in FXForms.m, then run the Edit > Refactor > Convert to Objective-C ARC... tool in Xcode and make sure all files that you wish to use ARC for (including FXForms.m) are checked.

Creating a form

To create a form object, just make any new NSObject subclass that conforms to the FXForm protocol, like this:

@interface MyForm : NSObject <FXForm>

@end

The FXForm protocol has no compulsory methods or properties. The FXForms library will inspect your object and identify all public and private properties and use them to generate the form. For example, suppose you wanted to have a form containing an "Email" and "Password" field, and a "Remember Me" switch; you would define it like this:

@interface MyForm : NSObject <FXForm>

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

@end

That's literally all you have to do. FXForms is really smart; much more so than you might expect:

  • Fields will appear in the same order you declare them in your class
  • Fields will automatically be assigned suitable control types, for example, the rememberMe field will be displayed as a UISwitch, the email field will automatically have a keyboard of type UIKeyboardTypeEmailAddress and the password field will automatically have secureTextEntry enabled.
  • Field titles are based on the key name, but camelCase is automatically converted to a Title Case, with intelligent handling of ACRONYMS, etc.
  • Modifying values in the form will automatically assign those values back to your model object. You can use custom setter methods and/or KVO to intercept the changes if you need to perform additional logic.
  • If your form contains subforms (properties that conform to the FXForm protocol), or view controllers (e.g for terms and conditions pages), they will automatically be instantiated if they are nil - no need to set default values.

These default behaviors are all inferred by inspecting the property type and name using Objective-C's runtime API, but they can also all be overridden if you wish - that's covered later under Tweaking form behavior

Displaying a form (basic)

To display your form in a view controller, you have two options: FXForms provides a UIViewController subclass called FXFormViewController that is designed to make getting started as simple as possible. To set up FXFormViewController, just create it as normal and set your form as follows:

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

You can then display the form controller just as you would do any ordinary view controller. FXFormViewController contains a UITableView, which it will create automatically as needed. If you prefer however, you can assign your own UITableView to the tableView property and use that instead. You can even initialize the FXFormViewController with a nib file that creates the tableView.

FXFormViewController is designed to be subclassed, just like a regular UIViewController or UITableViewController. In most cases, you'll want to subclass FXFormViewController so you can add your form setup logic and action handlers.

It is a good idea to place the FXFormViewController (or subclass) inside a UINavigationController. This is not mandatory, but if the form contains subforms, these will be pushed onto its navigationController, and if that does not exist, the forms will not be displayed.

Like UITableViewController, FXFormViewController will normally assign the tableView as the main view of the controller. Unlike UITableViewController, it doesn't have to be - you can make your tableView a subview of your main view if you prefer.

Like UITableViewController, FXFormViewController implements the UITableViewDelegate protocol, so if you subclass it, you can override the UITableViewDelegate and UIScrollViewDelegate methods to implement custom behaviors. FXFormViewController is not actually the direct delegate of the tableView however, it is the delegate of its formController, which is an instance of FXFormController. The formController acts as the tableView's delegate and datasource, and proxies the UITableViewDelegate methods back to the FXFormViewController via the FXFormControllerDelegate protocol.

Unlike UITableViewController, FXFormViewController does not implement UITableViewDataSource protocol. This is handled entirely by the FXFormController, and it is not recommended that you try to override or intercept any of the datasource methods.

Displaying a form (advanced)

The FXFormViewController is pretty flexible, but sometimes it's inconvenient to be forced to use a particular base controller class. For example, you may wish to use a common base class for all your view controllers, or display a form inside a view that does not have an associated controller.

In the former case, you could add an FXFormViewController as a child controller, but in the latter case that wouldn't work. To use FXForms without using FXFormViewController, you can use the FXFormController directly. To display a form using FXFormController, you just need to set the form and tableView properties, and it will do the rest. You can optionally bind the FXFormController's delegate property to be notified of UITableView events.

When using a custom form view controller in this way, some interactions are still handled for you (e.g. adjusting the table view content inset when the keyboard is presented), but you will need to add other view logic yourself, such as reloading the table when the UIViewController appears on screen.

Here is example code for a custom form view controller:

@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

Tweaking form behavior

FXForm's greatest strength is that it eliminates work by guessing as much as possible. It can't guess everything however, and it sometimes guesses wrong. So how do you correct it?

You may find that you don't want all of your object properties to become form fields; you may have private properties that are used internally by your form model for example, or you may just wish to order the fields differently to how you've arranged your properties in the interface.

To override the list of form fields, implement the optional -fields method of your form:

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

The fields method should return an array of strings, dictionaries, or a mixture. In the example we have returned strings; these map to the names of properties of the form object. If you return an array of names like this, these fields will replace the automatically generated field list.

The -fields method will be called again every time the form is reassigned to the formController. That means that you can generate the fields dynamically, based on application logic. For example, you could show or hide certain fields based on other properties.

In addition to omitting and rearranging fields, you may wish to override their attributes. There are two ways to do this: One way is to add a method to the form object, such as -(NSDictionary *)[name]Field; where name is the property that the field relates to. This method returns a dictionary of properties that you wish to override (see Form field properties, below). For example, if we wanted to override the title of the email field, we could do it like this:

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

Alternatively, you can return a dictionary in the -fields array instead of a string. If you do this, you must include the FXFormFieldKey so that FXForms knows which field you are overriding:

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

These two approaches are equivalent.

You may wish to add additional, virtual form fields (e.g. buttons or labels) that don't correspond to any properties on your form class. You can do this by implementing the -fields method, but if you're happy with the default fields and just want to add some extra fields at the end, you can override the -extraFields method instead, which works the same way, but leaves in place the default fields inferred from the form class:

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

Similarly, if you only want to display a subset of the form object's properties in your form, but don't want to have to list all the properties you want to keep in the -fields method just for the sake of excluding a few of them, you can use the -excludedFields method to specify just the names of properties you don't want to include.

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

Grouping fields

You may wish to group your form fields into sections in the form to make it ease to use. FXForms handles grouping in a very simple way - you just add an FXFormFieldHeader or FXFormFieldFooter attribute to any field and it will start/end the section at that point. The FXFormFieldHeader/Footer can be either a string that will be displayed as the header or footer text for the section, or a custom UIView instance or subclass. If you don't want a header or footer, just supply an empty string or NSNull value.

In the following example, we have four fields, and we've split them into two groups, each with a header:

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

Alternatively, since we aren't overriding any other field properties, we could have done this more cleanly by using the following approach:

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

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

Form field properties

The list of form field properties that you can set are as follows. Most of these have sensible defaults set automatically. Note that the string values of these constants are declared in the interface - you can assume that the string values of these constants will no change in future releases, and you can safely use these values in (for example) a plist used to configure the form.

static NSString *const FXFormFieldKey = @"key";

This is the name of the related property of the form object. If your field isn't backed by a real property, this might be the name of a getter method used to populate the field value. It's also possible to have completely virtual fields (such as buttons) that do not have a key at all.

static NSString *const FXFormFieldType = @"type";

This is the field type, which is used to decide how the field will be displayed in the table. The type is used to determine which type of cell to use to represent the field, but it may also be used to configure the cell (a single cell class may support multiple field types). The type is automatically inferred from the field property declaration, but can be overridden. Supported types are listed under Form field types below, however you can supply any string as the type and implement a custom form cell to display and/or edit it.

static NSString *const FXFormFieldClass = @"class";

This is the class of the field value. For primitive types, this will be the class used to box the value when accessed via KVC (e.g. NSNumber for numeric values, or NSValue for struct types). This is automatically determined for all properties of the form, so you rarely need to set it yourself. For form properties that you add yourself using the -fields or -extraFields methods, it is sometimes helpful to specify this explicitly. A good example would be if you are adding view controller or subform fields, where the class cannot usually be inferred automatically. The value provided can be either a Class object or a string representing the class name.

static NSString *const FXFormFieldCell = @"cell";

This is the class of the cell used to represent the field. By default this value is not specified on the field-level; instead, the FXFormController maintains a map of fields types to cell classes, which allows you to override the default cells used to display a given field type on a per-form level rather than having to do it per-field. If you do need to provide a special one-off cell type, you can use this property to do so. The value provided can be either a Class object or a string representing the class name.

static NSString *const FXFormFieldTitle = @"title";

This is the display title for the field. This is automatically generated from the key by converting from camelCase to Title Case, and then localised by running it through the NSLocalizedString() macro. That means that instead of overriding the title using this key, you can do so in your strings file instead if you prefer.

static NSString *const FXFormFieldPlaceholder = @"placeholder";

This is the placeholder value to display when the field value is nil or empty. This is typically a string, but doesn't have to be, for example it could be an NSDate for a date field, or a UIImage for an image field. When used with an options or multi-select field, the placeholder will appear as the first item in the options list, and can be used to reset the field to nil / no value.

static NSString *const FXFormFieldDefaultValue = @"default";

This is a default value to use when the field value is nil. This can be useful when creating forms dynamically as the default values can be set directly in the fields array instead of separately in the form's values. It's also a way to ensure that a field value can never be set to nil by the user. Note that the default value is different from the placeholder value, as it will actually be stored in the form itself. If a default value is set, the placeholder will never appear. Default values only work reliably for object types - since zero is potentially a meaningful value for an integer or float property, it will not be replaced by the default value.

static NSString *const FXFormFieldOptions = @"options";

For any field type, you can supply an array of supported values, which will override the standard field with a checklist of options to be selected instead. The options can be NSStrings, NSNumbers or any other object type. You can supply an FXFormFieldValueTransformer to control how the option values are displayed in the list. Alternatively, if you use a custom object for the values, you can implement the -(NSString *)fieldDescription; method to control how it is displayed. See Form field options below for more details.

static NSString *const FXFormFieldTemplate = @"template";

If the field is an NSArray or NSOrderedSet, FXForms allows the user to add, edit and remove items. By default FXForms assumes that the values in the collection are of type FXFormFieldTypeText, however you can override this using the FXFormFieldTemplate dictionary. The FXFormFieldTemplate dictionary can contains most of the same types of value as an ordinary field dictionary, and should be used to describe all the attributes of the elements in the collection.

static NSString *const FXFormFieldValueTransformer = @"valueTransformer";

Sometimes the value you wish to display for a field may not match the value you store. For example, you might want to display a date in a particular format, or convert a locale code into its human-readable equivalent. The FXFormFieldValueTransformer property lets you specify either a conversion block or an NSValueTransformer to use for converting the field value to a string. If a value transformer is provided, it will be used instead of calling the -fieldDescription method of the field's value object. You can supply either an instance of NSValueTransformer or the name of an NSValueTransformer subclass. If the form field has an options array, the value transformer will also be used to control how the options are displayed in the list. The FXFormFieldValueTransformer can be reversible, in which case it will be also be used to convert input values before storing them in the form.

static NSString *const FXFormFieldAction = @"action";

This is an optional action to be performed by the field. The value can be either a string representing the name of a selector, or a block, and will be executed when the field is activated. If the action is specified as a selector, the target is determined by cascading up the responder chain from the cell until an object is encountered that responds to it. That means that you could choose to implement this action method on the tableview, its superview, the view controller, the app delegate, or even the window. If your form is presented as a subform of another form, you can also implement actions methods for subforms in the view controller for their parent form.

For non-interactive fields, the action will be called when the cell is selected; for fields such as switches or textfields, it will fire when the value is changed. When using a selector, the action method can accept either zero or one argument. The argument supplied will be the sender, which is typically a form field cell, (a UITableViewCell conforming to the FXFormFieldCell protocol), from which you can access the field model, and from that the form itself.

static NSString *const FXFormFieldSegue = @"segue";

This is a UIStoryboardSegue to be performed when the field is tapped. This can be either be a UIStoryboardSegue subclass (or a string containing the name of a UIStoryboardSegue subclass), an instance of a UIStoryboardSegue subclass, or a string representing the identifier of a segue attached to the form view controller. Note that in the latter case, the segue must be attached to the same controller as the form, or it will crash when invoked.

If the FXFormFieldSegue property is a segue instance or identifier, it will be invoked when the field is tapped. If it is a segue subclass, this segue will be instantiated and used to handle the transition when displaying a subform or sub-controller.

static NSString *const FXFormFieldHeader = @"header";

This property provides an optional section header to display before the field. The value can be either a string or a UIView instance or subclass (or a string containing the name of a UIView subclass). The height of the header will be inferred from the view, or you can override it using the UITableViewDelegate. By default, its value will be inferred automatically for subforms based on the name of the subform property. Supply an empty string or NSNull value to create a section partition without a title.

static NSString *const FXFormFieldFooter = @"footer";

This property provides an optional section footer string to display after the field. The value can be either a string or a UIView instance or subclass (or a string containing the name of a UIView subclass). The height of the footer will be inferred from the view, or you can override it using the UITableViewDelegate. Supply an empty string or NSNull value to create a section partition without a footer, or just omit the FXFormFieldFooter key altogether.

static NSString *const FXFormFieldInline = @"inline";

Fields whose values is another FXForm, or which have a supplied options array, will normally be displayed in a new FXFormViewController, which is pushed onto the navigation stack when you tap the field. You may wish to display such fields inline within same tableView instead. You can do this by setting the FXFormFieldInline property to @YES.

static NSString *const FXFormFieldSortable = @"sortable";

Fields of type NSArray or NSOrderedSet can optionally display sorting controls so that the user can change the item order. Set the FXFormFieldSortable property to YES to enabled this feature.

static NSString *const FXFormFieldViewController = @"controller";

Some types of field may be displayed in another view controller, which will be pushed onto the navigation stack when the field is selected. By default this class is not specified on the field-level; instead, the FXFormController maintains a map of fields types to controller classes, which allows you to override the default controller used to display a given field type on a per-form level rather than having to do it per-field. If you do need to provide a special one-off controller type, the FXFormFieldViewController property lets you specify the controller to be used on a per-field basis. FXFormViewController can be either a UIViewController instance or class (or a string containing the name of a class). The controller specified must conform to the FXFormFieldViewController protocol. By default, such fields will be displayed using the FXFormViewController class.

Form field types

static NSString *const FXFormFieldTypeDefault = @"default";

This is the default field type, used if no specific type can be determined.

static NSString *const FXFormFieldTypeLabel = @"label";

This type can be used if you want the field to be treated as non-interactive/read-only. Form values will be displayed by converting the value to a string using the -fieldDescription method. This maps to the standard NSObject -description method for all built-in types, but you can override it for your own custom value classes.

static NSString *const FXFormFieldTypeText = @"text";

By default, this field type will be represented by an ordinary UITextField with default autocorrection.

static NSString *const FXFormFieldTypeLongText = @"longtext";

This type represents multiline text. By default, this field type will be represented by an expanding UITextView.

static NSString *const FXFormFieldTypeURL = @"url";

Like FXFormFieldTypeText, but with a keyboard type of UIKeyboardTypeURL, and no autocorrection.

static NSString *const FXFormFieldTypeEmail = @"email";

Like FXFormFieldTypeText, but with a keyboard type of UIKeyboardTypeEmailAddress, and no autocorrection.

static NSString *const FXFormFieldTypePassword = @"password";

Like FXFormFieldTypeText, but with secure text entry enabled, and no autocorrection.

static NSString *const FXFormFieldTypeNumber = @"number";

Like FXFormFieldTypeText, but with a numeric keyboard, and input restricted to a valid number.

static NSString *const FXFormFieldTypeInteger = @"integer";

Like FXFormFieldTypeNumber, but restricted to integer input.

static NSString *const FXFormFieldTypeUnsigned = @"unsigned";

Like FXFormFieldTypeInteger, but for unsigned values. Uses number pad by default.

static NSString *const FXFormFieldTypeFloat = @"float";

Like FXFormFieldTypeNumber, but indicates value is primitive (not-nillable)

static NSString *const FXFormFieldTypeBoolean = @"boolean";

A boolean value, set using a UISwitch control by default.

static NSString *const FXFormFieldTypeOption = @"option";

Like FXFormFieldTypeBoolean, but this type is used for toggle options and by default it creates a checkmark control instead of a switch.

static NSString *const FXFormFieldTypeDate = @"date";

A date value, selected using a UIDatePicker.

static NSString *const FXFormFieldTypeTime = @"time";

A time value, selected using a UIDatePicker.

static NSString *const FXFormFieldTypeDateTime = @"datetime";

A date and time, selected using a UIDatePicker.

static NSString *const FXFormFieldTypeImage = @"image"

An image, selected using a UIImagePickerController.

Form field options

When you provide an options array for a form field, the field input will be presented as a list of options to tick. How this list of options is converted to the form value depends on the type of field:

If the field type matches the values in the options array, selecting the option will set the selected value directly, but that may not be what you want. For example, if you have a list of strings, you may be more interested in the selected index than the value (which may have been localised and formatted for human consumption, not machine interpretation). If the field type is numeric, and the options values are not numeric, it will be assumed that the field value should be set to the index of the selected item, instead of the value.

If the field is a collection type (such as NSArray, NSSet, etc.), the form will allow the user to select multiple options instead of one. Collections are handled as followed, depending on the class of the property: If you use NSArray, NSSet and NSOrderedSet, the selected values will be stored directly in the collection; If you use an NSIndexSet, the indexes of the values will be stored; If you use NSDictionary, both the values and their indexes will be stored. For ordered collection types, the order of the selected values is guaranteed to match the order in the options array.

Multi-select fields can also be used with NS_OPTIONS-style bitfield enum values. Just use an integer or enum as your property type, and then specify a field type of FXFormFieldTypeBitfield. You can then either specify explicit bit values in your options by using NSNumber values, or let FXForms infer the bit value from the option index.

NOTE: the actual values defined in your enum are not available to FXForms at runtime, so the selected values will be purely determined by the index of value of the options in the FXFormFieldOptions value. If your enum values are non-sequential, or do not begin at zero, the indices won't match the options indexes. To define enum options with non-sequential values, you can specify explicit numeric option values and use FXFormFieldValueTransformer to display human readable labels, like this:

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];
    }};
}

Cell configuration

If you want to tweak some properties of the field cells, without subclassing them, you can actually set any cell property by keyPath, just by adding extra values to your field dictionary. For example, this code would turn the textLabel for the email field red:

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

This code would disable auto-capitalisation for the name field:

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

Cells are not recycled in the FXForm controller, so you don't need to worry about cleaning up any properties that you set in this way. Be careful of overusing "stringly typed" code such as this however, as errors can't be caught at compile time. For heavy customisation, it is better to create cell subclasses and override properties in the -setField: method.

Custom cells

FXForms provides default cell implementations for all supported fields. You may wish to provide additional cell classes for custom field types, or even replace all of the FXForm cells with custom versions for your application.

There are two levels of customisation possible for cells. The simplest option is to subclass one of the existing FXFormCell classes, which all inherit from FXFormBaseCell. These cell classes contain a lot of logic for handling the various different field types, but also expose the views and controls used, for easy customisation.

When subclassing an existing cell type, you can override the setUp, update and didSelectWithTableView:controller: methods (optionally calling [super ...] if you want to inherit the original cell's behaviors). The setUp method will be called once when the cell is created, and the update method will be called each time the field value is updated.

If you already have a base cell class and don't want to base your cells on FXFormBaseCell, you can create an FXForms-compatible cell from scratch by subclassing UITableViewCell and adopting the FXFormFieldCell protocol.

Your custom cell must have a property called field, of type FXFormField. FXFormField is a wrapper class used to encapsulate the properties of a field, and also provides a way to set and get the associated form value (via the field.value virtual property). You cannot instantiate FXFormField objects directly, however they can be accessed and enumerated via methods on the FXFormController.

Once you have created your custom cell, you can use it as follows:

  • If your cell is used only for a few specific fields, you can use the FXFormFieldCell property to use it for a particular form field
  • If your cell is designed to handle a particular field type (or types), you can tell the formController to use your custom cell class for a particular type using the -registerCellClass:forFieldType: method of FXFormController.
  • If your cell is designed to handle a particular field value class (or subclass), you can tell the formController to use your custom cell class for a particular value class using the -registerCellClass:forFieldClass: method of FXFormController.
  • If you want to completely replace all cells with your own classes, use the -registerDefaultFieldCellClass: method of FXFormController. This replaces all default cell associations for all field types with your new cell class. You can then use -registerCellClass:forFieldType: to add additional cell classes for specific types.

Swift Compatibility

FXForms is fully compatible with Swift, with the following caveats:

  • Your forms objects must inherit from NSObject, or de declared using the @objc qualifier.
  • For collection fields, you must use NSArray, NSDictionary, NSOrderedSet, etc. Swift's strongly typed collections won't work.
  • If your form objects are declared in a different module to your main app, FXForm's field value class inference may not work correctly, in which case you can explicitly specify the field class by adding the following method to your form object for each field that doesn't work:
func fieldThatDoesntWorkField() -> NSDictionary {
    return [FXFormFieldClass: fieldThatDoesntWork.dynamicType]
}

Release notes

Version 1.2.14

  • Fixed issues wth keyboard show/hide
  • Removed namespaces from nib names for Swift compatibility
  • Fixed over-large margins in landscape mode on iPad
  • Set accessibility values for text labels
  • Fixed image picker being presented when cancel pressed

Version 1.2.13

  • Exposed nextCell property on FXFormBaseCell
  • Fixed long UITextView's to scroll to the the cursor position instead of the bottom of the UITextView.
  • Made sure that when the keyboard is dismissed the former tableView contentInsets are restored.
  • Make custom cell config cascade down to options views
  • Fix to resolve crash bug when used with BaseModel
  • Fixed warnings on Xcode 7 beta (well, suppressed mostly)

Version 1.2.12

  • Custom titles for template fields are no longer displayed inside each field item, they are only used for the "Add Item" button title.
  • Fixed another crash relating to using scalar default values for collection type fields
  • Reverse value transforms should now work correctly

Version 1.2.11

  • Field descriptions for collections now respect FXFieldValueTransformer
  • Using Scalar values as default value for collection type fields now works transparently

Version 1.2.10

  • Fixed crash when displaying photo picker on iPad

Version 1.2.9

  • Cells defined using nibs now infer their height form the nib unless overridden
  • Option picker can now be dismissed by tapping field again, like date picker

Version 1.2.8

  • Fixed incorrect type inference for fields with a segue property
  • Date picker can now be dismissed by tapping date field again

Version 1.2.7

  • Fixed bug where button-type fields (ones with an action but no editable value) were not correctly inferred

Version 1.2.6

  • Improved valueClass inference, especially for template fields
  • FXFormImagePickerCell now lets you select camera or photo library

Version 1.2.5

  • Fixed crash when form section has a footer but no header

Version 1.2.4

  • hash, description, etc. no longer show up on iOS7 for builds built with the 8.1 SDK
  • FXFormViewController can now be either a view controller class or instance

Version 1.2.3

  • Added a fix when using Swift to allow FXForms to automatically infer the types of forms and controllers, as it can with Objective-C
  • Now throws an exception if you try to present a subform when not embedded inside a UINavigationController

Version 1.2.2

  • Fixed bug where subforms would be overwritten by a new instance

Version 1.2.1

  • Fixed issue where table footer spacing would incorrectly be shown even when no footer text was set
  • Fixed crash relating to the use of default values
  • Made a small compatibility fix for Swift
  • Added Swift example project

Version 1.2

  • Collection fields types, such as NSArray, NSSet, NSOrderedSet, etc. can now be edited by adding, removing and sorting items
  • Exposed the setUp and update methods of FXFormsBaseCell for simpler subclassing
  • Added FXFormsDefaultCell that implements standard behaviors (for simpler subclassing)
  • Added FXFormFieldTemplate for creating template values for collections
  • Added FXFormFieldSegue property for specifying a segue to perform when field is tapped
  • Added FXFormFieldTypePhone field type
  • Added FXFormFieldTypeUnsigned field type
  • Added FXFormOptionSegmentsCell class
  • Added FXFormFieldDefault for specifying a default value for form fields
  • Added ability to register cell and controller classes based on field value class as well as type
  • Fixed bug in stepper field where labels didn't resize after value change
  • Fixed bug where image preview in FXImagePickerCell would be displayed with incorrect width
  • Fixed handling of NSURL fields
  • Type inference now works better for dynamic fields
  • Added dynamic fields example (loading form field descriptions from a JSON file)
  • Added indexPathForField: method to FXFormController
  • FXForm tableView is now always in edit mode - this may affect layout for custom cells
  • Specified FXFormFieldValueTransformer object can now be reversible
  • Textfield form values are now updated live during editing
  • Added -excludedFields method for excluding certain fields from form
  • Now ignores standard @properties such as hash and description, introduced in iOS 8
  • You can now use a UIView class or instance as the value for FXFormFieldHeader/Footer

Version 1.1.6

  • Options fields with numeric values are now correctly displayed
  • Action block will now be called when an options field is updated
  • Action blocks are no longer called when tapping subform field cells
  • Fixed crash when using placeholder values with options fields
  • Added FXFormFieldTypeFloat
  • Added dependent fields example

Version 1.1.5

  • Virtual fields without keys no longer crash when the form object is an NSManagedObject subclass

Version 1.1.4

  • FXForms now nils out all control delegates & datasources correctly to prevent crashes when form is dismissed
  • The FXFormImagePickerCell image is no longer drawn with incorrect alignment
  • FXFormTextViewCell can now display placeholder text when empty

Version 1.1.3

  • Using Field method to set form properties is no longer overridden by defaults
  • Only mess with the content inset/offset when the view controller is not a UITableViewController
  • It should now be easier to use nibs to lay out cell subclasses without losing standard functionality
  • Using FXFormFieldTypeLabel now works more consistently

Version 1.1.2

  • Fixed incorrect forwarding of scrollViewWillBeginDragging event
  • Fields of type FXFormFieldTypeBitfield are now handled correctly again (broken in 1.1.1)
  • It is now possible to create custom cell classes without inheriting all the standard styling logic
  • Added example of creating a custom form cell subclass using a nib file (CustomButtonExample)
  • FXForms will no longer try to auto-instantiate NSManagedObjects if they are nil (this would crash previously)

Version 1.1.1

  • Fixed bug with indexed options fields
  • FXFormOptionPickerCell selected index is now set correctly when tabbing between fields

Version 1.1

  • Added support for multi-select option fields - just use a collection type such NSArray, NSSet or NSIndexSet for your options field
  • Added FXFormFieldTypeBitfield for NS_OPTIONS-type multi-select enum values
  • Added FXFormFieldOptionPickerCell as an alternative way to display options fields (does not support multi-select)
  • Nested forms now propagate form actions back to their parent form view controller as well as up to the app delegate
  • Added parentFormController property to FXFormController
  • FXFormField action property is now a block instead a of a selector (can be specified as either in form dictionary)
  • Added FXFormFieldPlaceholder value to be displayed when value is nil / empty
  • Keyboard will now display "next" in cases where next cell acceptsFirstResponder
  • Added FXFormFieldTypeImage and FXFormImagePickerCell
  • Added FXFormFieldTypeLongText for multiline text
  • Added FXFormFieldValueTransformer for adapting field values for display
  • It is now possible to create completely virtual form objects by overriding setValue:forKey: to set properties
  • Added FXFormFieldViewController property for specifying custom form field view controllers
  • Added additional example projects to demonstrate the new features
  • Button-type fields (ones with only an action and no key) now have centered text by default
  • It is now possible to override UITableViewCellStyle without subclassing by using "style" keypath in field config

Version 1.0.2

  • Fixed crash when attempting to set UITextInputTraits properties on a FXFormTextFieldCell
  • Fixed potential crash when numeric field type is used with string properties

Version 1.0.1

  • Subform FXFormController instances now correctly inherit registered cells from the parent controller
  • Fields of type FXFormFieldOption with associated actions will now still be toggled before action fires

Version 1.0

  • Initial release

fxforms's People

Contributors

adamcian avatar ashton-w avatar bartvandendriessche avatar bobspryn avatar bumaociyuan avatar donnalea avatar felipelc avatar gantman avatar gtranchedone avatar hanneskaeufler avatar januzellij avatar jhersh avatar jlajlar avatar joepestro avatar masa-beheim avatar nicklockwood avatar pjcook avatar plandem avatar qfish avatar rynaardb avatar samuele-mrapps avatar sdesimone avatar streeter avatar theill avatar waterskier2007 avatar wimbledon avatar yakubbaev avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fxforms's Issues

Confused about usage

Hello,

First and foremost, sorry for bringing this up as an issue, but I couldn't wrap my head around some way of doing this:

I have a basic signup form and have two issues with it so far:

  1. Is there any way of styling the whole form without having to do it on a field-by-field basis?
  2. I have a small options table that should display some text and an image for each option.
    I tried creating an FXFormBaseCell subclass, but, how would I specify how to fill out each cell? Do I need to create a new FXFormField? And finally, upon selection (single selection), how can I display that data (image + text) in the original form?

Thank you!

Localization

Hi, does your framework have any support for localization? I think it would be awesome if for any field it would simply make the title of the field NSLocalizedString(fieldTitle, @"");
Then I wouldn't have to implement the 'Fields' method to get the titles localized.

How to Style Label for DatePicker & PickerView

Was trying to style the label for date picker and picker view but couldn't find a way for that. I've attach the screenshot that you can see the selected value font are different from the others.
screen shot 2014-04-04 at 5 53 45 pm

Add Image field type

For filling UIImage properties, using UIImagePickerController for selection.

Yay or Nay? If welcome I'll try a PR soon

ReadOnly Mode

I need to use my FXForm also in ReadOnly mode. In this mode I set all the fields type as FXFormFieldTypeLabel, but I need also to hide all the empty fields (the hidden fields will be displayed in Edit mode).
All the fields are set via Fields method as UndefinedKeys, there aren't class properties.
Can you suggest me the best way to hide or show empty cells?

Thank you

Coredata relation option picker

Not sure if this is there already, but can't seem to get it to work.

How to display and set another MO entity from a relationship.

For example on the Client Form which points to SalesAgent Entity. How to pick the Sales Agent (which has name, id, etc) display just name and then assign the selected SalesAgent MO to the Client form?

Customize headers

Is is currently possible to customize the section headers, e.g. changing the font? Or to provide a custom UIView for the section headers?

Custom text field cell

I've tried to subclass FXFormTextFieldCell with little to no success. All I'd like to do is add an image view to the left of the cell, with a 58pt x-value. This is my attempt:

#import "FXForms.h"

@interface POnboardingCell : FXFormTextFieldCell

@property (strong, nonatomic) IBOutlet UIImageView *iconImageView;

@end
#import "POnboardingCell.h"

@interface POnboardingCell ()

@property (strong, nonatomic) IBOutlet UITextField *textField;

@end

@implementation POnboardingCell

@synthesize textField = _textField;

- (void)awakeFromNib {
    self.textField.frame = CGRectMake(58, 10, 254, 30);
    self.textField.textAlignment = NSTextAlignmentLeft;

    if (!self.textField.superview) {
        [self.contentView addSubview:self.textField];
    }

    self.iconImageView.backgroundColor = [UIColor greenColor];
}

@end

There is also a .xib file to accompany the class.

The view loads up, but I cannot interact with the text field.

Proposal: Conditional/Dependent fields

Have you had any thoughts about how to structure Conditional and Dependent fields? I'm working through very specific use-case of replicating Apple's event creation form (EKEventEditViewController) for a custom calendar that cannot use EKEventStore. Problem here is the date-related fields:

First problem is the 'All day' UISwitch field. When enabled, it changes the 'Start' and 'End' field from DateTime to just a Date picker. So this would be a 'Dependent' field relationship to change that setting if value changes.

Second problem is the 'Repeat' field. It's currently a picker and if it equals anything other than 'Never' the form adds a 'End Repeat' field, which is also a picker (or poentially date). So this would be a 'Conditional' field that should only appear if another field's has a particular value or values (possibly using KVO?)

Again, this is very specific use-case, but I'm sure similiar concepts would be beneficial to more forms. Any thoughts on how to work these cases into FXForms? Happy to help contribute, just didn't want to do work one way if you have already considered and just haven't implemented yet.

Can't access form field values from view controller

I love this library so far, but can't figure out how to properly access the values in the form from the view controller. I'm trying to access them when a rightbarbuttonitem is clicked, but keep getting (null) - see below.

I must be missing something really obvious. A nudge in the right direction would be highly appreciated.

FXForm View controller:

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.

// Add the right bar button item
    UIBarButtonItem *saveButton = [[UIBarButtonItem alloc] initWithTitle:@"Save" style:UIBarButtonItemStylePlain target:self action:@selector(addProvider)];
    self.navigationItem.rightBarButtonItem = saveButton;

}

- (void)addProvider
{
    ManualEntryProviderForm *mepf = self.formController.form;
    NSLog(@"Address1: %@", mepf.address1); // Shows Address1: (null) in console
}

View controller that displays the FXForm View controller:

- (void)clickProviderNotFound {
    ManualEntryProviderViewController *fvc = [[ManualEntryProviderViewController alloc] init];

    fvc.formController.form = [[ManualEntryProviderForm alloc] init];
    [self.navigationController pushViewController:fvc animated:YES];
}

null model value crashes app

I just started using FXForms - looks really promising for reducing work I have to do. My first attempt to implement a form using an NSManagedObject as my FXForm (assume this is valid). Here's my exception:

2014-04-05 16:16:58.530 Lacrosse-Stats[16049:60b] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<team 0xd0781b0> valueForUndefinedKey:]: the entity (null) is not key value coding-compliant for the key "state".'

Apparently, there is no value for the "state" field (a US State). It is not mandatory in my app. I would assume FXForm can handle null values so I must be doing something wrong. Any suggestions?

Automatic firstResponder

Is there a way to immediately make the first textfield the firstresponder so the keyboard immediately pops up?

Issues with showing MFMailComposeViewController

If I set a property to be MFMailComposeViewControler and the deploy device doesn't have a mail account configured, the form will show the "No Mail Accounts" alert view when the view appears, and then again before the cell is displayed. I've tried to set a default value for the property, but I can't get around it. Any advice?

Reload the form from within the form

As you say in your ReadMe, I've used a custom setter to intercept a value change within the form. I then use this value to recalculate another value within the same form. How can I now update this form? I've tried calling the 'Fields' method but this doesn't update the data visibly. I know it has been changed because if I scroll the cell out of view and then back the value is changed correctly. But I somehow need to reload the tableview from within the form, do you have an idea how to do this?

Model not updating

This is relevant to #52: Is there a way to use a FXFormBaseCell subclass with a text field to update the model object?

TextLabel Alignment Center

Hi, I've tried doing this in the fields method for a specific field:
@"textLabel.textAlignment":[NSNumber numberWithInteger:NSTextAlignmentCenter]

But it doesn't work unfortunately. Is there a way this can work?

FXFormFieldPlaceholder not available

When I try to set the FXFormFieldPlaceholder like this:

- (NSArray *)fields
{
    return @[
             @{ FXFormFieldKey : @"genderType", FXFormFieldTitle : NSLocalizedString(@"REGISTER_DU_BIST", nil), FXFormFieldPlaceholder : @"test" },
}

I get

Use of undeclared identifier 'FXFormFieldPlaceholder'; did you mean 'FXFormFieldHeader'?

Indeed I can't find the declaration for it in FXForms.h. Documentation says there is such a property?!

Keyboard Show and table content inset

On a very simply form I have 3 fields, the second is for date selection. When I select it, the table content moves upwards when there's no need to. It works fine with the normal keyboard/text fields, just not the date picker.

FXFormFieldOptions - on row tap, not loading options

Hey,

Need some help! I've setup FXForms, great job! But when I setup FXFormFieldOptions, the row appears, but when I tap on it, the next view with the options doesn't load, nothing happens when I tap the row, apart from the changing background colour of the cell.

Please help! Cheers.

Get selected index when field type is numeric

Hi Nick,

with this issue I refer to the part of the documentation that states:

If the field type is numeric, and the options values are not numeric, it will be assumed that the field value should be set to the index of the selected item, instead of the value.

When I understand this correctly declaring a field as numeric like this and passing an array with some country strings would result in the property value being set to the selected index in the option table view (countryIndex is of type NSInteger)(?

@{ FXFormFieldKey : @"countryIndex", FXFormFieldTitle : NSLocalizedString(@"COUNTRY", nil), FXFormFieldOptions : self.countries },

However when I output the property value of countryIndex after I select an option and reload the table view I always get a value of 0. Also there is no checkmark set to the selected option in the table view listing the countries.

Do I misinterpret the documentation here?

Crash when Canceling for with Object Picker visible

It appears that the delegates are not being cleared when deallocating the Form Objects so if they attempt to fire a delegate method, it results in a selector fired on a deallocated object.

I've fixed it here: boxer@5a4da60

(Sorry - too deep on the fork for a simple pull request and no time to make it work - there's more code to be written!)

Format text on option field

Hi Nick, how do you format the label used to show the currently selected option in an option field like this? I tried optionLabel but doesn't work.

return @{FXFormFieldKey: @"secretQuestion",
FXFormFieldTitle: @"QUESTION (*)",
FXFormFieldOptions: questions,
@"textLabel.font": kFontNormal(14),
@"optionLabel.font": kFontNormal(14)};

Updating the Placeholder string (Model/View communication)

Hi Nick,

I have question regarding updating the placeholder and model view communication. I've set up a form where people can search for their city. Therefor I set up a view controller form field like this:

@{ FXFormFieldKey : @"cityViewController", FXFormFieldTitle : NSLocalizedString(@"CITY", nil), FXFormFieldPlaceholder : self.selectedCity },

The cityViewController is presented with a search interface which works quite well. In there I declared a @property NSDictionary to hold the users selection from the search results. I want to communicate that selection back to the form model and adjust the placeholder string to the current value of the selected city.

I can see that in cityViewController.selectedEntry the current selection is stored so that's working ok. But how can I adjust the placeholder to display the current city accordingly?

I wonder if there might be a better way to do what I try?
Thanks so much for your work and help!

Placeholder not displayed using FXFormFieldTypeLongText

Hi,
first of all, great work! When I use "FXFormFieldType: FXFormFieldTypeLongText" property, placeholder is not shown.

Example:

  • Placeholder is not shown: @{FXFormFieldKey: @"citazione", FXFormFieldType: FXFormFieldTypeLongText,FXFormFieldPlaceholder: profilo.prfCitazionePreferita,
    @"textLabel.color": mainColor,
    @"textLabel.font": labelFont}
  • Placeholder is shown: @{FXFormFieldKey: @"citazione",FXFormFieldPlaceholder: profilo.prfCitazionePreferita,
    @"textLabel.color": mainColor,
    @"textLabel.font": labelFont}

Suggestions?

Best regards
Costantino

Remove first section header

Hello,
How do I remove first section header (set its height to 0)?
Do I need to subclass entire formcontroller?

Thank you.

Dismissal of inputView

Hi,

First of all - thanks a lot for sharing this project. It's coming in handy.

I believe the following should be added before pushing to a new VC:
[controller.view endEditing:YES];

Otherwise the various inputs stay visible when you pop back to the form from the options screen.

Example for Advanced method

Hi,

Really like FXForms, the idea and the implementation! thanks for sharing your code with us !

Um, also it would be awesome if you can make an example app using the advanced method !

How to Add Custom Button

Hi there,

Is there any way can let me add a custom button to the form? I've look through the FXForms.h library but don't see any button related functions there.

Correct me if I am wrong ya ๐Ÿ‘ hope you have a nice day ahead.

Keyboard Next field

If I have multiple fields, the user has to manually tap the next field while it's much more user-friendly if instead of 'Done', the keyboard displays 'Next' IF there's still another field below the current field, and it then jumps to the next field when pressing Next! :)

Allow keyboard selection

I want to use decimal keyboard for number inputs but I can not force the keyboard I want.

Thanks!

Fields method

I need to define the fields without using class properties because I create dynamically the fields to display reading them from the database.
So I can see correctly all the fields in the table but I can't get their entered value on submit.

MyForm *form = cell.field.form;

If I iterate all form.fields items I see only:
{
key = field1;
title = Field1;
type = text;
}
{
key = field2;
title = Field2;
type = text;
}
[...]
How can I get the values?

Thank you

Crash after `reloadData`

Hey there,

so i'll start simple, something visual is worth a thousand words:

crash - fxforms

Now i'll explain a bit what we can see in that gif.

I have a two properties, one NSString and one NSNumber. The first one is shown as a label not editable and the second is a UISliderCell that have action on the first one.

Now the code is fairly simple:

Interface

@interface sizeForm : NSObject <FXForm>

@property (nonatomic, retain) NSString  *maxStorageSize;
@property (nonatomic, retain) NSNumber  *limitStorageSize;

@end

implementation

- (void)setLimitStorageSize:(NSNumber *)limitStorageSize
{
    if (_limitStorageSize == limitStorageSize || [_limitStorageSize isEqualToNumber:limitStorageSize])
        return ;

    ReleaseAndNil(_limitStorageSize);
    _limitStorageSize = [limitStorageSize retain];

    if (!_limitStorageSize)
        return ;

    [[settingsManager instance] save:_limitStorageSize forKey:kMaxSize];
    self.maxStorageSize = [_formatter stringFromNumberOfBits:_limitStorageSize];

    [[NSNotificationCenter defaultCenter] postNotificationName:@"ReloadFxForm" object:self userInfo:@{@"form" : self}];
}

Now you can see that the maxStorageSize (NSString) is being edited by the NSNumber property setter. The question then was, how to update the label, more specifically how to tell the form to refresh the cell / label.

Well what i thought, is to tell the formViewController to update / reload the tableview through a notification (that last line).

Which for now simple call this:

- (void)handleNotification:(NSNotification*)note
{
    NSLog(@"Got notified: %@", note);

    [_formTableView reloadData];
}

Now as you can see, it works fine for a while, but then when you release the slider and try to play with it again it crash automatically.

I think there is something with the cells being reloaded and the field being destroyed but i lack some informations to fix this. (maybe dispatch to a thread or using synchronized ?)

the crash

here, i'll give you as much informations as i can on the crash:

image 2014-04-17 at 12 31 22 pm

backtrace

* thread #1: tid = 0x4f9204, 0x026840b2 libobjc.A.dylib`objc_msgSend + 14, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x20b8a8ac)
    frame #0: 0x026840b2 libobjc.A.dylib`objc_msgSend + 14
  * frame #1: 0x0007d4f8 -ios-app`-[FXFormSliderCell valueChanged](self=0x0b8a0190, _cmd=0x000c00db) + 264 at FXForms.m:2227
    frame #2: 0x02686880 libobjc.A.dylib`-[NSObject performSelector:withObject:withObject:] + 77
    frame #3: 0x011b23b9 UIKit`-[UIApplication sendAction:to:from:forEvent:] + 108
    frame #4: 0x011b2345 UIKit`-[UIApplication sendAction:toTarget:fromSender:forEvent:] + 61
    frame #5: 0x012b3bd1 UIKit`-[UIControl sendAction:to:forEvent:] + 66
    frame #6: 0x012b3fc6 UIKit`-[UIControl _sendActionsForEvents:withEvent:] + 577
    frame #7: 0x01364b42 UIKit`-[UISlider beginTrackingWithTouch:withEvent:] + 1051
    frame #8: 0x012b2c79 UIKit`-[UIControl touchesBegan:withEvent:] + 106
    frame #9: 0x015482e3 UIKit`_UIGestureRecognizerUpdate + 7166
    frame #10: 0x011f1a5a UIKit`-[UIWindow _sendGesturesForEvent:] + 1291
    frame #11: 0x011f2971 UIKit`-[UIWindow sendEvent:] + 1021
    frame #12: 0x011c45f2 UIKit`-[UIApplication sendEvent:] + 242
    frame #13: 0x011ae353 UIKit`_UIApplicationHandleEventQueue + 11455
    frame #14: 0x0287e77f CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15
    frame #15: 0x0287e10b CoreFoundation`__CFRunLoopDoSources0 + 235
    frame #16: 0x0289b1ae CoreFoundation`__CFRunLoopRun + 910
    frame #17: 0x0289a9d3 CoreFoundation`CFRunLoopRunSpecific + 467
    frame #18: 0x0289a7eb CoreFoundation`CFRunLoopRunInMode + 123
    frame #19: 0x041695ee GraphicsServices`GSEventRunModal + 192
    frame #20: 0x0416942b GraphicsServices`GSEventRun + 104
    frame #21: 0x011b0f9b UIKit`UIApplicationMain + 1225
    frame #22: 0x0001b549 `main(argc=1, argv=0xbfffe8b8) + 169 at main.m:29

If i can be of any help, let me know.

Once again great work !

FXFormTextViewCell resizing the cell height

When the FXFormTextViewCell is resized due to multiple lines input, the tableview's other cells below the textViewCell does not update their position properly. This issue is evident when you push to the subForm and return to the parent form.

Tableview doesn't reload when option is selected

Hi,

I currently have my own form view controller which conforms to the protocol
<FXFormControllerDelegate>. I've set it up as in the docs:

self.formController = [[FXFormController alloc] init];
self.formController.form = [[MKSignupFormInput alloc] init];
self.formController.tableView = self.tableView;

I've got a field in the form which allows user's to select their country:

@{
           FXFormFieldKey : @"country",
           FXFormFieldPlaceholder : @"Select your country...",
           FXFormFieldTitle : @"Country",
           FXFormFieldType : @"option",
           FXFormFieldOptions : [CountryPicker countryNames]
}

This field, when tapped, pushes a view controller to show these countries (non-custom). When I select an option, and then tap to go back to the form, the cell within the form is still set as selected, and the value does not get updated to be my selected option.

The workaround I currently use is to manually reload the tableview from my custom form view controller in viewWillAppear.

ceeK

Intercept input value and change another field in the form

Thank you for this great great library it really makes building forms much easier.

Im having a problem with changing a field's options based on the user input in another field. Lets assume I have a list of 3 products: Juice, water, coffee. if the user selects juice or water then he/she can select multiple options for these products at once. If the selected product is however coffee then only one option can be selected (See code below).

I have no idea how to get the select product value and change the options based on that using FXForms. In the documentation you mention KVO and custom setter, but since Im new to IOS development I find it hard to understand without some examples, .

I hope you can give an example on how to intercept input values and update fields based on input :).

typedef NS_ENUM(NSInteger,Product)
{
Juice = 0,
water,
coffee
};

typedef NS_OPTIONS(NSInteger, Options)
{
Option1 = 1 << 0,
Option2 = 1 << 1,
Option3 = 1 << 2
};
@interface ProductSelectionForm : NSObject < FXForm >
@Property (nonatomic, assign)Product productList;
@Property (nonatomic, assign) Options productOptions;
@EnD

Form Validation

Are there any plans to include form/field validation as a feature for FXForms?

Accessing cell properties without subclassing FXFormBaseCell

I wanted to be able to access basic cell properties without subclassing and I noticed that basically the field is mapped on the cell, hence this works:

         @"backgroundColor": [UIColor yellowColor],

So the dictionary becomes:

return @{FXFormFieldKey: @"email",
         FXFormFieldTitle: ICLocalizedString(@"FORM_EMAIL*", @""),
         FXFormFieldHeader: ICLocalizedString(@"FORM_ACCESS_DATA", @""),
         FXFormFieldPlaceholder: ICLocalizedString(@"FORM_EMAIL_PLACEHOLDER", @""),
         FXFormFieldType: FXFormFieldTypeEmail,
         @"backgroundColor": [UIColor yellowColor],
         @"textLabel.font": kFontNormal(14),
         @"textField.font": kFontNormal(14)};

Do you agree with this approach or you see anything wrong with it?

Add field from FXFormViewController

I'm currently using FXForms to edit account details in an app I'm working on.
I would like to be able to programmatically add a button to the bottom of the table (to remove the account).
I don't want to have this field on all the FXForms I create using the same class, since the same form is also used for adding new accounts (and they can not be removed, obviously).

Any suggestions on how this can be done?

Enum NSInteger Bug

Changing the gender definition in the basic example to

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

does not change the output after submitting the form. (gender is still 0 if male is selected).

I think theres something wrong with the enum handling.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.