1. 程式人生 > >ios 新表單利器

ios 新表單利器

https://github.com/nicklockwood/FXForms

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 7.1 (Xcode 5.1)
  • Earliest supported deployment target - iOS 5.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 typeUIKeyboardTypeEmailAddress 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 UIViewControllersubclass called FXFormViewController that is designed to make getting started as simple as possible. To set upFXFormViewController, 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 orUITableViewController. 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 UITableViewControllerFXFormViewController 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 UITableViewControllerFXFormViewController 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 theFXFormViewController via the FXFormControllerDelegate protocol.

Unlike UITableViewControllerFXFormViewController 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 FXFormControllerdirectly. 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 ofUITableView 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.

Finally, 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"},
            ];
}

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 is a string that will be displayed as the header or footer text for the section. If you don't want any text, just supply an empty string.

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 doneed 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 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 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. TheFXFormFieldValueTransformer 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 ofNSValueTransformer 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.

static NSString *const FXFormFieldAction = @"action";

This is an optional action to be performed when 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, it's 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, (aUITableViewCell conforming to the FXFormFieldCell protocol), from which you can access the field model, and from that the form itself.

static NSString *const FXFormFieldHeader = @"header";

This property provides an optional section header string to display before the field. Supply an empty string 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. Supply an empty string to create a section partition without a footer.

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 FXFormFieldInlineproperty to @YES.

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 

相關推薦

ios 利器

https://github.com/nicklockwood/FXForms Purpose FXForms is an Objective-C library for easily creating table-based forms on iOS. It

ios默認樣式

one appear input ron 拖拽 :focus rom type -o 摘自:http://blog.sina.com.cn/s/blog_7d796c0d0102uyd2.html 可惜不能直接轉到博客園。 input[type="button"], in

ios form上傳圖片

1.使用微博開發的一個“傳送帶圖片微博”的介面來測試,這是介面地址,這裡面明確說明需要使用multipart/form-data格式提交圖片。關於使用微博開放平臺api、授權之類的就不說了。 2.multipart/from-data是一種進行表單提交時的訊息格式。表單提交資料的時候,預設型別是

ios驗證工具

新建一個NSObject類,起一個工具類的名字,我的是QCTools 然後把下邊程式碼分 .h   .m  檔案粘進去,結束 本表單工具主要包括 字串為空判斷 判斷是否為手機號 判斷時候為身份證號 判斷是否為郵箱 判斷是否為

Vue+Element動態生成並新增驗證

首先有一個這樣的需求,表單中預設有一個聯絡人資訊,使用者可以再新增新的聯絡人資訊 點選新增更多聯絡人之後 官方文件中有寫用v-for來實現新增表單,但是那是單表單的新增,現在多表單的新增,可以考慮的實現方法是先寫死一個必須的表單,需要新增的兩個表單放在一個div裡

HTML5

第一部分INPUT新型別,新增了以下型別: 1.email型別 - 判斷字串中是否包含"@"符號,注意的是不能以"@"開始、不能以"@"結束 2.搜尋型別 - search 3.URL型別 - 判斷字串中是否包含"http:",注意的是以"http:"開始,驗證通過,以"h

H5屬性

1. autocomplete 表單自動完成: 書寫格式autocomplete=“on/off”  不加此屬性則預設是on,出於某些方面考慮需要關閉的話就要加上,然後值設定為off; 2. autofocus 自動聚焦  當頁面載入完成後,游標自動聚焦到設定有此屬性的欄目

HTML5特性1(控制元件/選擇器/JSON/data)

1.HTML5新控制元件 其實新控制元件不難理解,一段程式碼足以說明 HTML部分 <form action="#"> <input type="email" /> //電子郵箱文字框,跟普

2.9 使用Eureka快速優雅地建立一個漂亮的 [iOS開發中的神兵利器]

1. 本節課將為您演示,如何使用第三方庫,快速建立強大的表單。首先確保在您的專案中,已經安裝了所需的第三方庫。雙擊此處檢視安裝配置檔案。 2. 根據配置檔案中的相關設定,安裝第三方庫。安裝完成之後,雙擊開啟此處的專案檔案。 3. 然後在左側的專案導航區,開啟檢視控制器的程式碼

2.11 建立星期選項和擁有Float標籤的文字框 [iOS開發中的神兵利器]

1. 本節課將為您演示如何建立一個星期表單,以及擁有浮動標籤的文字框。首先開啟上一節下載的示例資料夾。 2. 然後將需要使用到的星期樣式的表單介面檔案,拖動到我們的專案中。 3. 在彈出的檔案匯入確認視窗中,點選完成按鈕,確認檔案的匯入。 4. 然後在左側的專案導航區,開啟檢

使用iframe實現頁面無刷提交

fin 友好 frame you itl 圖片 項目需求 scripts tel iframe提交表單其實比ajax要方便一些,當然ajax也有ajax的好處,只是ajax編碼處理有時有些麻煩,雖然經過轉碼是可以解決中文問題,但如果直接使用iframe不存這些問題了,下面來

跟KingDZ學HTML5之十一 HTML5 Form 元素

rmi 出現 第一個 blog inpu tput form itl scrip 新的課程又開始,哈哈,最近的文章更新比較快,希望大家跟上俺的步伐啊,呵呵,但是每當看到閱讀量,哎,還真不多,可是俺還要堅持寫下去,不知道,大家是不是都沒有在研究HTML5呢? 這節課程,講的是

Form提交後頁面刷不跳轉的實現

cti value 提交 頁面刷新 splay pan form提交 屬性。 ram <form action="" id="" method="post" target="nm_iframe">   <input type="text" id="i

AJAX PHP無刷form提交的簡單實現(推薦)

username mime win root 支持 對象 希望 meta {} 下面小編就為大家帶來一篇AJAX PHP無刷新form表單提交的簡單實現(推薦)。小編覺得挺不錯的,現在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧 ajax.php <

HTML5基礎知識匯總_(2)自己定義屬性及特性

一行 當前 down js日期 日期 mark 定義 ++ bing 自己定義屬性data-* 說起這個屬性,事實上如今非經常見了;怎麽說呢,由於在一些框架都能看到他的身影!!! 比方Jquery mobile,裏面非常頻繁的使用了這個屬性; 這個

input ,button, textarea 1)使用disabled , 2) 顯示值, 3) 提交. 4) jquery.form.js ajaxSubmit() 無刷ajax提交.

成功 isa post key input 技術分享 and () 去除 1.使用disabled input , button textarea 可以 被 禁用, 禁用的效果 : 1) 上面的點擊事件無法使用 --- button : 下面的 oncli

layer,Jquery,validate實現驗證,刷頁面,關閉子頁面

名稱 ron primary ocl span () bsp money 新頁面 1、表單驗證            //獲取父層 var index = parent.layer.getFrameIndex(window.na

form 無刷頁面提交

刷新 提交表單 無需 目標 none isp one log pos 表單可實現無刷新頁面提交,無需頁面跳轉,如下: 通過一個隱藏的iframe實現, form表單的target設置為iframe的name名稱,form提交目標位當前頁面iframe則不會刷新頁面 <

阻止提交刷頁面的問題

ID map utf-8 doc pad default eve lse bsp <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"><head id="Head1">&l

html5中

RKE targe 屬性 .com mar chrome 發送 cal 私鑰 HTML5 的新的表單元素: HTML5 擁有若幹涉及表單的元素和屬性。 本章介紹以下新的表單元素: datalist keygen output 瀏覽器支持 Input typeIEF