├── screenshot.png
├── TableForm.xcodeproj
├── xcuserdata
│ ├── gazollajunior.xcuserdatad
│ │ ├── xcdebugger
│ │ │ └── Breakpoints_v2.xcbkptlist
│ │ └── xcschemes
│ │ │ ├── xcschememanagement.plist
│ │ │ └── TableForm.xcscheme
│ └── gazolla.xcuserdatad
│ │ └── xcschemes
│ │ └── xcschememanagement.plist
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ ├── xcuserdata
│ │ ├── gazolla.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ │ └── gazollajunior.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
└── project.pbxproj
├── TableForm
├── FormView.swift
├── Info.plist
├── Assets.xcassets
│ └── AppIcon.appiconset
│ │ └── Contents.json
├── Base.lproj
│ └── LaunchScreen.storyboard
├── TableViewController.swift
├── MyFormView.swift
├── AppDelegate.swift
├── FormViewController.swift
└── FormCells.swift
├── TableFormTests
├── Info.plist
└── TableFormTests.swift
├── TableFormUITests
├── Info.plist
└── TableFormUITests.swift
└── README.md
/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gazolla/TableForm/HEAD/screenshot.png
--------------------------------------------------------------------------------
/TableForm.xcodeproj/xcuserdata/gazollajunior.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/TableForm.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/TableForm.xcodeproj/project.xcworkspace/xcuserdata/gazolla.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gazolla/TableForm/HEAD/TableForm.xcodeproj/project.xcworkspace/xcuserdata/gazolla.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/TableForm.xcodeproj/project.xcworkspace/xcuserdata/gazollajunior.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gazolla/TableForm/HEAD/TableForm.xcodeproj/project.xcworkspace/xcuserdata/gazollajunior.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/TableForm.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/TableForm/FormView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FormView.swift
3 | // Form
4 | //
5 | // Created by Gazolla on 10/03/17.
6 | // Copyright © 2017 Gazolla. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class FormView: UITableView {
12 |
13 | var completion: (() -> Void)?
14 |
15 | override func layoutSubviews() {
16 | super.layoutSubviews()
17 | self.completion?()
18 | }
19 |
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/TableForm.xcodeproj/xcuserdata/gazolla.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | TableForm.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/TableFormTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/TableFormUITests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/TableForm.xcodeproj/xcuserdata/gazollajunior.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | TableForm.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | 08177D1B1D46A3B000228592
16 |
17 | primary
18 |
19 |
20 | 08177D2A1D46A3B000228592
21 |
22 | primary
23 |
24 |
25 | 08177D351D46A3B000228592
26 |
27 | primary
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/TableFormTests/TableFormTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TableFormTests.swift
3 | // TableFormTests
4 | //
5 | // Created by Gazolla on 25/07/16.
6 | // Copyright © 2016 Gazolla. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | @testable import TableForm
11 |
12 | class TableFormTests: XCTestCase {
13 |
14 | override func setUp() {
15 | super.setUp()
16 | // Put setup code here. This method is called before the invocation of each test method in the class.
17 | }
18 |
19 | override func tearDown() {
20 | // Put teardown code here. This method is called after the invocation of each test method in the class.
21 | super.tearDown()
22 | }
23 |
24 | func testExample() {
25 | // This is an example of a functional test case.
26 | // Use XCTAssert and related functions to verify your tests produce the correct results.
27 | }
28 |
29 | func testPerformanceExample() {
30 | // This is an example of a performance test case.
31 | self.measure {
32 | // Put the code you want to measure the time of here.
33 | }
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/TableFormUITests/TableFormUITests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TableFormUITests.swift
3 | // TableFormUITests
4 | //
5 | // Created by Gazolla on 25/07/16.
6 | // Copyright © 2016 Gazolla. All rights reserved.
7 | //
8 |
9 | import XCTest
10 |
11 | class TableFormUITests: XCTestCase {
12 |
13 | override func setUp() {
14 | super.setUp()
15 |
16 | // Put setup code here. This method is called before the invocation of each test method in the class.
17 |
18 | // In UI tests it is usually best to stop immediately when a failure occurs.
19 | continueAfterFailure = false
20 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.
21 | XCUIApplication().launch()
22 |
23 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
24 | }
25 |
26 | override func tearDown() {
27 | // Put teardown code here. This method is called after the invocation of each test method in the class.
28 | super.tearDown()
29 | }
30 |
31 | func testExample() {
32 | // Use recording to get started writing UI tests.
33 | // Use XCTAssert and related functions to verify your tests produce the correct results.
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # TableForm
2 | Programmatically use of TableView to create data entry forms for iOS
3 |
4 | 
5 |
6 | ## Supported Platforms
7 |
8 | - iOS 11
9 | - swift 4
10 |
11 | ## Installing
12 |
13 | In order to install, you'll need to copy the `FormViewController`, `FormView` and `FormCells` files into your Xcode project.
14 |
15 | ## Usage
16 |
17 | ### create Fields:
18 |
19 | ```swift
20 | let name = Field(name:"name", title:"Nome:", cellType: NameCell.self)
21 | let birth = Field(name:"birthday", title:"Nascimento:", cellType: DateCell.self)
22 | let address = Field(name:"address", title:"Address:", cellType: TextCell.self)
23 | ```
24 |
25 | ### add Fields to Section:
26 |
27 | ```swift
28 | let sectionPersonal = [name, address, birth]
29 | ```
30 |
31 | ### group all Sections:
32 |
33 | ```swift
34 | let sections = [sectionPersonal, sectionProfessional, sectionButton]
35 | ```
36 |
37 |
38 | ### call ConfigureTable:
39 |
40 | ```swift
41 | let config = ConfigureForm(items: sections)
42 | ```
43 |
44 | ### Set the configuration to TableViewController:
45 | ```swift
46 | let main = FormViewController(config: config)
47 | ```
48 |
49 | ### Contact
50 |
51 | * Sebastian Gazolla Jr
52 | * [@gazollajr](http://twitter.com/gazollajr)
53 | * [http://about.me/gazolla](http://about.me/gazolla)
54 |
55 | ## License
56 |
57 | `TableForm` is licensed under the MIT license.
58 |
--------------------------------------------------------------------------------
/TableForm/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIRequiredDeviceCapabilities
28 |
29 | armv7
30 |
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 | UISupportedInterfaceOrientations~ipad
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationPortraitUpsideDown
41 | UIInterfaceOrientationLandscapeLeft
42 | UIInterfaceOrientationLandscapeRight
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/TableForm/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "20x20",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "20x20",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "29x29",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "29x29",
61 | "scale" : "2x"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "size" : "40x40",
66 | "scale" : "1x"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "size" : "40x40",
71 | "scale" : "2x"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "size" : "76x76",
76 | "scale" : "1x"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "size" : "76x76",
81 | "scale" : "2x"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "size" : "83.5x83.5",
86 | "scale" : "2x"
87 | }
88 | ],
89 | "info" : {
90 | "version" : 1,
91 | "author" : "xcode"
92 | }
93 | }
--------------------------------------------------------------------------------
/TableForm/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/TableForm/TableViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TableViewController.swift
3 | // GenericTable2
4 | //
5 | // Created by Sebastiao Gazolla Costa Junior on 04/08/16.
6 | // Copyright © 2016 Sebastiao Gazolla Costa Junior. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public struct ConfigureTable- {
12 | var items:[Item]
13 | var cellType:AnyClass
14 | var configureCell:(_ cell:UITableViewCell, _ item:Item, _ indexPath:IndexPath)->()
15 | var selectedRow:(_ controller:TableViewController
- , _ indexPath:IndexPath)->()
16 | }
17 |
18 | class TableViewController
- : UIViewController, UITableViewDelegate, UITableViewDataSource {
19 |
20 | var items:[Item] {
21 | didSet{
22 | self.tableView.reloadData()
23 | }
24 | }
25 |
26 | var error:Error?{
27 | didSet{
28 | print(error!)
29 | }
30 | }
31 |
32 | var cellType:AnyClass
33 | var configureCell:((_ cell:UITableViewCell, _ item:Item, _ indexPath:IndexPath)->())?
34 | var selectedRow:((_ controller:TableViewController
- , _ indexPath:IndexPath)->())?
35 | var deselectedRow:((_ controller:TableViewController
- , _ indexPath:IndexPath)->())?
36 | var selected:IndexPath?
37 |
38 | init(items:[Item], cellType:AnyClass){
39 | self.items = items
40 | self.cellType = cellType
41 | super.init(nibName: nil, bundle: nil)
42 | }
43 |
44 | init(config:ConfigureTable
- ){
45 | self.items = config.items
46 | self.cellType = config.cellType
47 | self.configureCell = config.configureCell
48 | self.selectedRow = config.selectedRow
49 | super.init(nibName: nil, bundle: nil)
50 | }
51 |
52 | required public init?(coder aDecoder: NSCoder) {
53 | fatalError("init(coder:) has not been implemented")
54 | }
55 |
56 | lazy var tableView:UITableView = {
57 | let tv = UITableView(frame: self.view.bounds, style: .grouped)
58 | tv.autoresizingMask = [.flexibleWidth, .flexibleHeight]
59 | tv.delegate = self
60 | tv.dataSource = self
61 | tv.register(self.cellType, forCellReuseIdentifier: "cell")
62 | return tv
63 | }()
64 |
65 | override func viewDidLoad() {
66 | super.viewDidLoad()
67 | self.view.addSubview(self.tableView)
68 | }
69 |
70 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
71 | return self.items.count
72 | }
73 |
74 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
75 | let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) //as! SummaryCell
76 | let item = self.items[indexPath.item]
77 | configureCell?(cell, item, indexPath)
78 | cell.selectionStyle = UITableViewCellSelectionStyle.none
79 |
80 | return cell
81 | }
82 |
83 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
84 | selectedRow?(self, indexPath)
85 | }
86 |
87 | func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
88 | deselectedRow?(self, indexPath)
89 | }
90 |
91 |
92 | }
93 |
--------------------------------------------------------------------------------
/TableForm.xcodeproj/xcuserdata/gazollajunior.xcuserdatad/xcschemes/TableForm.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
43 |
49 |
50 |
51 |
52 |
53 |
59 |
60 |
61 |
62 |
63 |
64 |
74 |
76 |
82 |
83 |
84 |
85 |
86 |
87 |
93 |
95 |
101 |
102 |
103 |
104 |
106 |
107 |
110 |
111 |
112 |
--------------------------------------------------------------------------------
/TableForm/MyFormView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MyFormView.swift
3 | // TableForm
4 | //
5 | // Created by Gazolla on 05/10/17.
6 | // Copyright © 2017 Gazolla. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class MyFormViewController: FormViewController {
12 |
13 | var gender:String? {
14 | didSet{
15 | if let cell = self.sections?[2][0], let gender = self.gender {
16 | (cell as! LinkCell).valueLabel.text = gender
17 | }
18 | }
19 | }
20 |
21 | func createFieldsAndSections()->[[Field]]{
22 | let name = Field(name:"name", title:"Name:", cellType: NameCell.self)
23 | let birth = Field(name:"birthday", title:"Birthday:", cellType: DateCell.self)
24 | let address = Field(name:"address", title:"Address:", cellType: TextCell.self)
25 | let sectionPersonal = [name, address, birth]
26 | let company = Field(name:"company", title:"Company:", cellType: TextCell.self)
27 | let position = Field(name:"position", title:"Position:", cellType: TextCell.self)
28 | let salary = Field(name:"salary", title:"Salary:", cellType: NumberCell.self)
29 | let sectionProfessional = [company, position, salary]
30 | let gender = Field(name: "gender", title:"Gender:", cellType: LinkCell.self)
31 | let sectionGender = [gender]
32 | return [sectionPersonal, sectionProfessional, sectionGender]
33 | }
34 |
35 | lazy var saveButton: UIBarButtonItem = {
36 | return UIBarButtonItem(barButtonSystemItem: .save, target: self, action: #selector(saveTapped))
37 | }()
38 |
39 | lazy var genderList = { ()-> TableViewController in
40 | let genders = ["male", "female"]
41 | let genderList = TableViewController(items:genders, cellType: UITableViewCell.self)
42 |
43 | genderList.configureCell = { (cell, item, indexPath) in
44 | cell.textLabel?.text = "\(item)"
45 | }
46 |
47 | genderList.selectedRow = { (controller, indexPath) in
48 | if let cell = controller.tableView.cellForRow(at: indexPath as IndexPath){
49 | cell.accessoryType = .checkmark
50 | controller.selected = indexPath
51 | self.gender = cell.textLabel?.text
52 | }
53 | controller.navigationController?.popViewController(animated: true)
54 | }
55 |
56 | genderList.deselectedRow = { (controller, indexPath) in
57 | if controller.selected != nil {
58 | if let cell = controller.tableView.cellForRow(at: controller.selected!){
59 | cell.accessoryType = .none
60 | }
61 | }
62 | }
63 |
64 | genderList.title = "Venues"
65 |
66 | return genderList
67 | }()
68 |
69 | override init(){
70 | super.init()
71 | let its = createFieldsAndSections()
72 | self.fields = its
73 | self.sections = buildCells(items: its)
74 | self.selectedRow = { [weak self] (form:FormViewController,indexPath:IndexPath) in
75 | let cell = form.tableView.cellForRow(at: indexPath)
76 | cell?.isSelected = false
77 | if cell is LinkCell {
78 | if (cell as! FormCell).name == "gender" {
79 | self?.navigationController?.pushViewController(self!.genderList, animated: true)
80 | }
81 | }
82 | }
83 | }
84 |
85 | override init(config:ConfigureForm){
86 | super.init(config:config)
87 | }
88 |
89 | required init?(coder aDecoder: NSCoder) {
90 | fatalError("init(coder:) has not been implemented")
91 | }
92 |
93 | override func viewDidLoad() {
94 | super.viewDidLoad()
95 | title = "Employee"
96 | navigationItem.rightBarButtonItem = saveButton
97 | navigationController?.navigationBar.prefersLargeTitles = true
98 | }
99 |
100 | override func viewDidAppear(_ animated: Bool) {
101 | super.viewDidAppear(animated)
102 | }
103 |
104 | @objc func saveTapped(){
105 | let dic = self.getFormData()
106 | let alertController = UIAlertController(title: "Form Data", message: dic.description, preferredStyle: .alert)
107 | //We add buttons to the alert controller by creating UIAlertActions:
108 | let actionOk = UIAlertAction(title: "OK",
109 | style: .default,
110 | handler: nil) //You can use a block here to handle a press on this button
111 |
112 | alertController.addAction(actionOk)
113 | self.present(alertController, animated: true, completion: nil)
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/TableForm/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // TableForm
4 | //
5 | // Created by Gazolla on 25/07/16.
6 | // Copyright © 2016 Gazolla. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 | var window: UIWindow?
15 |
16 | var nav: UINavigationController?
17 |
18 | func createFieldsAndSections()->[[Field]]{
19 | let name = Field(name:"name", title:"Nome:", cellType: NameCell.self)
20 | let birth = Field(name:"birthday", title:"Nascimento:", cellType: DateCell.self)
21 | let address = Field(name:"address", title:"Address:", cellType: TextCell.self)
22 | let sectionPersonal = [name, address, birth]
23 | let company = Field(name:"company", title:"Company:", cellType: TextCell.self)
24 | let position = Field(name:"position", title:"Position:", cellType: TextCell.self)
25 | let salary = Field(name:"salary", title:"Salary:", cellType: NumberCell.self)
26 | let sectionProfessional = [company, position, salary]
27 | let slider = Field(name: "test", title:"test:", cellType: SliderCell.self)
28 | let sectionSlider = [slider]
29 | let swap = Field(name: "cool", title:"Is it cool?", cellType: SwitchCell.self)
30 | let sectionSwap = [swap]
31 | let stepper = Field(name: "count", title:"Count:", cellType: StepperCell.self)
32 | let sectionStepper = [stepper]
33 | let save = Field(name: "Save", title:"Save", cellType: ButtonCell.self)
34 | let sectionButton = [save]
35 | return [sectionPersonal, sectionProfessional, sectionSlider, sectionSwap, sectionStepper, sectionButton]
36 | }
37 |
38 | func createConfigureTableStruct(formFields:[[Field]])->ConfigureForm{
39 |
40 | return ConfigureForm(fields: formFields, selectedRow: { (form, indexPath) in
41 | let cell = form.tableView.cellForRow(at: indexPath as IndexPath)
42 | if cell is ButtonCell {
43 | cell?.isSelected = false
44 | let dic = form.getFormData()
45 | let alertController = UIAlertController(title: "Form Data", message: dic.description, preferredStyle: .alert)
46 | //We add buttons to the alert controller by creating UIAlertActions:
47 | let actionOk = UIAlertAction(title: "OK",
48 | style: .default,
49 | handler: nil) //You can use a block here to handle a press on this button
50 |
51 | alertController.addAction(actionOk)
52 |
53 | self.nav?.present(alertController, animated: true, completion: nil)
54 | }
55 | })
56 |
57 | }
58 |
59 | func createForm()->FormViewController {
60 | let formFields = self.createFieldsAndSections()
61 | let config = self.createConfigureTableStruct(formFields: formFields)
62 | let myForm = FormViewController(config:config)
63 | myForm.title = "Form"
64 | let f = DateFormatter()
65 | f.dateStyle = .medium
66 | let hiddenData:[String:AnyObject] = ["id":0 as AnyObject]
67 | let data:[String:AnyObject] = ["name":"Sebastian Gazolla Jr" as AnyObject,
68 | "address":"SQN 315" as AnyObject,
69 | "birthday":Date() as AnyObject,
70 | "company":"Pineapple Computers" as AnyObject,
71 | "position":"Software Engineer" as AnyObject,
72 | "salary":"200,000.00" as AnyObject,
73 | "count":0.0 as AnyObject,
74 | "Frequencia":50.0 as AnyObject]
75 | myForm.data = data
76 | myForm.hiddenData = hiddenData
77 |
78 |
79 | return myForm
80 | }
81 |
82 | func createTabBar()->UITabBarController {
83 | let delegateFormNav = UINavigationController(rootViewController: createForm())
84 | let tabOneBarItem = UITabBarItem(title: "DelegateForm", image: UIImage(named: "DelegateForm"), selectedImage: UIImage(named: "DelegateForm"))
85 | delegateFormNav.tabBarItem = tabOneBarItem
86 |
87 | let tabTwoBarItem2 = UITabBarItem(title: "MyForm", image: UIImage(named: "MyForm"), selectedImage: UIImage(named: "MyForm"))
88 | let myFormNav = UINavigationController(rootViewController: MyFormViewController())
89 |
90 | myFormNav.tabBarItem = tabTwoBarItem2
91 |
92 | let tabBarCtrl = UITabBarController()
93 | tabBarCtrl.viewControllers = [delegateFormNav,myFormNav]
94 | return tabBarCtrl
95 | }
96 |
97 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
98 | self.window = UIWindow(frame: UIScreen.main.bounds)
99 | self.window!.rootViewController = createTabBar()
100 | self.window!.backgroundColor = UIColor.white
101 | self.window!.makeKeyAndVisible()
102 | return true
103 | }
104 |
105 | func applicationWillResignActive(_ application: UIApplication) {
106 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
107 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
108 | }
109 |
110 | func applicationDidEnterBackground(_ application: UIApplication) {
111 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
112 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
113 | }
114 |
115 | func applicationWillEnterForeground(_ application: UIApplication) {
116 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
117 | }
118 |
119 | func applicationDidBecomeActive(_ application: UIApplication) {
120 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
121 | }
122 |
123 | func applicationWillTerminate(_ application: UIApplication) {
124 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
125 | }
126 |
127 |
128 | }
129 |
130 |
--------------------------------------------------------------------------------
/TableForm/FormViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FormViewController.swift
3 | // Form
4 | //
5 | // Created by Gazolla on 10/03/17.
6 | // Copyright © 2017 Gazolla. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public struct Field{
12 | var name:String
13 | var title:String
14 | var value:AnyObject?
15 | var cellType:UITableViewCell.Type
16 | var cellId:String
17 |
18 | init(name:String, title:String, cellType: UITableViewCell.Type){
19 | self.name = name
20 | self.title = title
21 | self.cellType = cellType
22 | cellId = "\(cellType.self)\(name)"
23 | }
24 | }
25 |
26 | public struct ConfigureForm{
27 | var fields:[[Field]]
28 | var selectedRow:((_ form:FormViewController, _ indexPath:IndexPath)->())?
29 | var configureCell:((_ cell:FormCell, _ item:Field)->())?
30 |
31 | init (fields:[[Field]], selectedRow:((_ form:FormViewController, _ indexPath:IndexPath)->())?=nil, configureCell:((_ cell:UITableViewCell, _ item:Field)->())?=nil){
32 | self.fields = fields
33 | self.selectedRow = selectedRow
34 | self.configureCell = configureCell
35 | }
36 | }
37 |
38 |
39 | class FormViewController: UIViewController {
40 |
41 | var hiddenData:[String:AnyObject?]?
42 | var fields:[[Field]]?
43 | var sections:[[FormCell]]?
44 | var selectedRow:((_ form:FormViewController, _ indexPath:IndexPath)->())?
45 | var configureCell:((_ cell:FormCell, _ item:Field)->())?
46 | var buildCellsDone:(()->())?
47 | var data:[String:AnyObject?]?
48 |
49 |
50 | lazy var tableView:FormView = {
51 | let tv = FormView(frame: self.view.bounds, style: .grouped)
52 | tv.translatesAutoresizingMaskIntoConstraints = false
53 | tv.delegate = self
54 | tv.dataSource = self
55 | tv.keyboardDismissMode = .onDrag
56 |
57 | tv.completion = {
58 | DispatchQueue.main.async {
59 | if self.data != nil {
60 | self.setFormData()
61 | }
62 | }
63 | }
64 | return tv
65 | }()
66 |
67 | init(){
68 | super.init(nibName: nil, bundle: nil)
69 | }
70 |
71 | init(config:ConfigureForm){
72 | self.fields = config.fields
73 | self.selectedRow = config.selectedRow
74 | super.init(nibName: nil, bundle: nil)
75 | self.configureCell = config.configureCell
76 | if let its = self.fields {
77 | self.sections = self.buildCells(items: its)
78 | }
79 | }
80 |
81 | required init?(coder aDecoder: NSCoder) {
82 | fatalError("init(coder:) has not been implemented")
83 | }
84 |
85 | func buildCells(items:[[Field]])->[[FormCell]]?{
86 | var secs = [[FormCell]]()
87 | for section in items{
88 | var c = [FormCell]()
89 | for it in section {
90 | let instance = it.cellType.init(style: .default, reuseIdentifier: it.cellId) as! FormCell
91 | instance.name = it.name
92 | instance.textLabel?.text = "\(it.title)"
93 | c.append(instance)
94 | }
95 | secs.append(c)
96 | }
97 | return secs
98 | }
99 |
100 | func incrementIndexPath(_ indexPath: IndexPath) -> IndexPath? {
101 | var nextIndexPath: IndexPath?
102 | let rowCount = tableView.numberOfRows(inSection: (indexPath as NSIndexPath).section)
103 | let nextRow = (indexPath as NSIndexPath).row + 1
104 | let currentSection = (indexPath as NSIndexPath).section
105 |
106 | if nextRow < rowCount {
107 | nextIndexPath = IndexPath(row: nextRow, section: currentSection)
108 | }
109 | else {
110 | let nextSection = currentSection + 1
111 | if nextSection < tableView.numberOfSections {
112 | nextIndexPath = IndexPath(row: 0, section: nextSection)
113 | }
114 | }
115 | return nextIndexPath
116 | }
117 |
118 | func getFormData()->[String:AnyObject?]{
119 | if self.data == nil { self.data = [String:AnyObject?]() }
120 | var index:IndexPath? = IndexPath(row: 0, section: 0)
121 | while index != nil {
122 | let cell = self.tableView.cellForRow(at: index!)
123 | if cell is FormCell {
124 | let tuple = (cell as! FormCell).getCellData()
125 | self.data![tuple.key] = tuple.value as AnyObject?
126 | }
127 | index = self.incrementIndexPath(index!)
128 | }
129 | if let hiddenData = hiddenData {
130 | if hiddenData.count > 0{
131 | for (key, value) in hiddenData {
132 | data![key] = value
133 | }
134 | }
135 | }
136 | print(data!)
137 | return self.data!
138 | }
139 |
140 | func setFormData(){
141 | guard let sections = self.sections else { return }
142 | for (key, value) in self.data! {
143 | var index:IndexPath? = IndexPath(row: 0, section: 0)
144 | while index != nil {
145 | let cell = sections[(index! as NSIndexPath).section][(index! as NSIndexPath).item]
146 | if cell.name == key && value != nil {
147 | cell.setCellData(key: key, value: value!)
148 | }
149 | index = self.incrementIndexPath(index!)
150 | }
151 | }
152 | }
153 |
154 | override func viewDidLoad() {
155 | super.viewDidLoad()
156 | navigationController?.navigationBar.prefersLargeTitles = true
157 | self.view.addSubview(self.tableView)
158 | }
159 |
160 | override func viewDidAppear(_ animated: Bool) {
161 | super.viewDidAppear(animated)
162 | registerObservers()
163 | }
164 |
165 | override func viewDidDisappear(_ animated: Bool) {
166 | super.viewDidDisappear(animated)
167 | unregisterObservers()
168 | }
169 |
170 | override func updateViewConstraints() {
171 | super.updateViewConstraints()
172 | tableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
173 | tableView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
174 | tableView.rightAnchor.constraint(equalTo: view.safeAreaLayoutGuide.rightAnchor).isActive = true
175 | tableView.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor).isActive = true
176 | }
177 |
178 |
179 | func registerObservers() {
180 | NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(_:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
181 | NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(_:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
182 | NotificationCenter.default.addObserver(self, selector: #selector(textFieldTextDidEnd(_:)), name: NSNotification.Name.UITextFieldTextDidEndEditing, object: nil)
183 | }
184 |
185 | func unregisterObservers() {
186 | NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil)
187 | NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil)
188 | NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UITextFieldTextDidEndEditing, object: nil)
189 | }
190 |
191 | @objc func textFieldTextDidEnd(_ sender: NSNotification) {
192 | _ = self.getFormData()
193 | }
194 |
195 | @objc func keyboardWillShow(_ sender: NSNotification) {
196 | let info = sender.userInfo!
197 | let keyboardSize = (info[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue.height
198 |
199 | tableView.contentInset.bottom = keyboardSize
200 | }
201 |
202 | @objc func keyboardWillHide(_ sender: NSNotification) {
203 | tableView.contentInset.bottom = 0
204 | _ = self.getFormData()
205 | }
206 |
207 | }
208 |
209 | extension FormViewController:UITableViewDelegate {
210 |
211 | func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
212 | guard let section = self.sections?[indexPath.section] else { return 0.0 }
213 | let cell = section[indexPath.item]
214 | if (cell is SliderCell) {
215 | return 70
216 | } else if (cell is ButtonCell) {
217 | return 60
218 | } else if ((cell is TextViewCell) || (cell is ImageCell)){
219 | return 140
220 | } else {
221 | return 44
222 | }
223 | }
224 |
225 | func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
226 | return nil
227 | }
228 |
229 | func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
230 | return nil
231 | }
232 |
233 | func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
234 | guard let item = sections?[section][0] else { return 0.0 }
235 | if item is ButtonCell {
236 | return 20
237 | } else {
238 | return 3
239 | }
240 | }
241 |
242 | func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
243 | guard let item = sections?[section][0] else { return 0.0 }
244 | if item is ButtonCell {
245 | return 20
246 | } else {
247 | return 3
248 | }
249 | }
250 | }
251 |
252 | extension FormViewController:UITableViewDataSource {
253 |
254 | func numberOfSections(in tableView: UITableView) -> Int {
255 | print("numberOfSections")
256 | print("sections: \(self.sections?.count ?? -1)")
257 | if self.sections == nil { return 0 }
258 | return self.fields?.count ?? 0
259 | }
260 |
261 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
262 | print("numberOfRowsInSection")
263 | print("sections: \(self.sections?.count ?? -1)")
264 | if self.sections == nil { return 0 }
265 | return self.fields?[section].count ?? 0
266 | }
267 |
268 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
269 | guard let items = self.fields, let sections = self.sections else { return UITableViewCell() }
270 | let cell = sections[(indexPath as NSIndexPath).section][(indexPath as NSIndexPath).item]
271 | let item = items[indexPath.section][indexPath.item]
272 | configureCell?(cell, item)
273 | if indexPath.row + 1 == items[indexPath.section].count {
274 | cell.tag = 999
275 | } else {
276 | cell.tag = 0
277 | }
278 | return cell
279 | }
280 |
281 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
282 | for cell in tableView.visibleCells {
283 | if cell is TextCell{
284 | if ((cell as! TextCell).textField.isFirstResponder) == true{
285 | (cell as! TextCell).textField.resignFirstResponder()
286 | }
287 | }
288 | }
289 | selectedRow?(self, indexPath)
290 | }
291 | }
292 |
293 |
--------------------------------------------------------------------------------
/TableForm.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 08177D201D46A3B000228592 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08177D1F1D46A3B000228592 /* AppDelegate.swift */; };
11 | 08177D221D46A3B000228592 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 08177D211D46A3B000228592 /* Assets.xcassets */; };
12 | 08177D251D46A3B000228592 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 08177D231D46A3B000228592 /* LaunchScreen.storyboard */; };
13 | 08177D301D46A3B000228592 /* TableFormTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08177D2F1D46A3B000228592 /* TableFormTests.swift */; };
14 | 08177D3B1D46A3B000228592 /* TableFormUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08177D3A1D46A3B000228592 /* TableFormUITests.swift */; };
15 | 08177D491D46A3BD00228592 /* FormViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08177D481D46A3BD00228592 /* FormViewController.swift */; };
16 | 08177D4B1D46DD3A00228592 /* FormCells.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08177D4A1D46DD3A00228592 /* FormCells.swift */; };
17 | 08284B191F8688FD00367E83 /* MyFormView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08284B181F8688FD00367E83 /* MyFormView.swift */; };
18 | 08523E851F8969D8008D444D /* TableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08523E841F8969D8008D444D /* TableViewController.swift */; };
19 | 0860B2891F86D01E00D76378 /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = 0860B2881F86D01E00D76378 /* README.md */; };
20 | 0882883E1E738F1B00DDA1C6 /* FormView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0882883D1E738F1B00DDA1C6 /* FormView.swift */; };
21 | /* End PBXBuildFile section */
22 |
23 | /* Begin PBXContainerItemProxy section */
24 | 08177D2C1D46A3B000228592 /* PBXContainerItemProxy */ = {
25 | isa = PBXContainerItemProxy;
26 | containerPortal = 08177D141D46A3B000228592 /* Project object */;
27 | proxyType = 1;
28 | remoteGlobalIDString = 08177D1B1D46A3B000228592;
29 | remoteInfo = TableForm;
30 | };
31 | 08177D371D46A3B000228592 /* PBXContainerItemProxy */ = {
32 | isa = PBXContainerItemProxy;
33 | containerPortal = 08177D141D46A3B000228592 /* Project object */;
34 | proxyType = 1;
35 | remoteGlobalIDString = 08177D1B1D46A3B000228592;
36 | remoteInfo = TableForm;
37 | };
38 | /* End PBXContainerItemProxy section */
39 |
40 | /* Begin PBXFileReference section */
41 | 08177D1C1D46A3B000228592 /* TableForm.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TableForm.app; sourceTree = BUILT_PRODUCTS_DIR; };
42 | 08177D1F1D46A3B000228592 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
43 | 08177D211D46A3B000228592 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
44 | 08177D241D46A3B000228592 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
45 | 08177D261D46A3B000228592 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
46 | 08177D2B1D46A3B000228592 /* TableFormTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TableFormTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
47 | 08177D2F1D46A3B000228592 /* TableFormTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TableFormTests.swift; sourceTree = ""; };
48 | 08177D311D46A3B000228592 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
49 | 08177D361D46A3B000228592 /* TableFormUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TableFormUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
50 | 08177D3A1D46A3B000228592 /* TableFormUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TableFormUITests.swift; sourceTree = ""; };
51 | 08177D3C1D46A3B000228592 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
52 | 08177D481D46A3BD00228592 /* FormViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormViewController.swift; sourceTree = ""; };
53 | 08177D4A1D46DD3A00228592 /* FormCells.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormCells.swift; sourceTree = ""; };
54 | 08284B181F8688FD00367E83 /* MyFormView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyFormView.swift; sourceTree = ""; };
55 | 08523E841F8969D8008D444D /* TableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableViewController.swift; sourceTree = ""; };
56 | 0860B2881F86D01E00D76378 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; };
57 | 0882883D1E738F1B00DDA1C6 /* FormView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormView.swift; sourceTree = ""; };
58 | /* End PBXFileReference section */
59 |
60 | /* Begin PBXFrameworksBuildPhase section */
61 | 08177D191D46A3B000228592 /* Frameworks */ = {
62 | isa = PBXFrameworksBuildPhase;
63 | buildActionMask = 2147483647;
64 | files = (
65 | );
66 | runOnlyForDeploymentPostprocessing = 0;
67 | };
68 | 08177D281D46A3B000228592 /* Frameworks */ = {
69 | isa = PBXFrameworksBuildPhase;
70 | buildActionMask = 2147483647;
71 | files = (
72 | );
73 | runOnlyForDeploymentPostprocessing = 0;
74 | };
75 | 08177D331D46A3B000228592 /* Frameworks */ = {
76 | isa = PBXFrameworksBuildPhase;
77 | buildActionMask = 2147483647;
78 | files = (
79 | );
80 | runOnlyForDeploymentPostprocessing = 0;
81 | };
82 | /* End PBXFrameworksBuildPhase section */
83 |
84 | /* Begin PBXGroup section */
85 | 08177D131D46A3B000228592 = {
86 | isa = PBXGroup;
87 | children = (
88 | 0860B2881F86D01E00D76378 /* README.md */,
89 | 08177D1E1D46A3B000228592 /* TableForm */,
90 | 08177D2E1D46A3B000228592 /* TableFormTests */,
91 | 08177D391D46A3B000228592 /* TableFormUITests */,
92 | 08177D1D1D46A3B000228592 /* Products */,
93 | );
94 | sourceTree = "";
95 | };
96 | 08177D1D1D46A3B000228592 /* Products */ = {
97 | isa = PBXGroup;
98 | children = (
99 | 08177D1C1D46A3B000228592 /* TableForm.app */,
100 | 08177D2B1D46A3B000228592 /* TableFormTests.xctest */,
101 | 08177D361D46A3B000228592 /* TableFormUITests.xctest */,
102 | );
103 | name = Products;
104 | sourceTree = "";
105 | };
106 | 08177D1E1D46A3B000228592 /* TableForm */ = {
107 | isa = PBXGroup;
108 | children = (
109 | 08523E841F8969D8008D444D /* TableViewController.swift */,
110 | 08177D1F1D46A3B000228592 /* AppDelegate.swift */,
111 | 08177D211D46A3B000228592 /* Assets.xcassets */,
112 | 08177D231D46A3B000228592 /* LaunchScreen.storyboard */,
113 | 08177D261D46A3B000228592 /* Info.plist */,
114 | 0882883D1E738F1B00DDA1C6 /* FormView.swift */,
115 | 08177D481D46A3BD00228592 /* FormViewController.swift */,
116 | 08177D4A1D46DD3A00228592 /* FormCells.swift */,
117 | 08284B181F8688FD00367E83 /* MyFormView.swift */,
118 | );
119 | path = TableForm;
120 | sourceTree = "";
121 | };
122 | 08177D2E1D46A3B000228592 /* TableFormTests */ = {
123 | isa = PBXGroup;
124 | children = (
125 | 08177D2F1D46A3B000228592 /* TableFormTests.swift */,
126 | 08177D311D46A3B000228592 /* Info.plist */,
127 | );
128 | path = TableFormTests;
129 | sourceTree = "";
130 | };
131 | 08177D391D46A3B000228592 /* TableFormUITests */ = {
132 | isa = PBXGroup;
133 | children = (
134 | 08177D3A1D46A3B000228592 /* TableFormUITests.swift */,
135 | 08177D3C1D46A3B000228592 /* Info.plist */,
136 | );
137 | path = TableFormUITests;
138 | sourceTree = "";
139 | };
140 | /* End PBXGroup section */
141 |
142 | /* Begin PBXNativeTarget section */
143 | 08177D1B1D46A3B000228592 /* TableForm */ = {
144 | isa = PBXNativeTarget;
145 | buildConfigurationList = 08177D3F1D46A3B000228592 /* Build configuration list for PBXNativeTarget "TableForm" */;
146 | buildPhases = (
147 | 08177D181D46A3B000228592 /* Sources */,
148 | 08177D191D46A3B000228592 /* Frameworks */,
149 | 08177D1A1D46A3B000228592 /* Resources */,
150 | );
151 | buildRules = (
152 | );
153 | dependencies = (
154 | );
155 | name = TableForm;
156 | productName = TableForm;
157 | productReference = 08177D1C1D46A3B000228592 /* TableForm.app */;
158 | productType = "com.apple.product-type.application";
159 | };
160 | 08177D2A1D46A3B000228592 /* TableFormTests */ = {
161 | isa = PBXNativeTarget;
162 | buildConfigurationList = 08177D421D46A3B000228592 /* Build configuration list for PBXNativeTarget "TableFormTests" */;
163 | buildPhases = (
164 | 08177D271D46A3B000228592 /* Sources */,
165 | 08177D281D46A3B000228592 /* Frameworks */,
166 | 08177D291D46A3B000228592 /* Resources */,
167 | );
168 | buildRules = (
169 | );
170 | dependencies = (
171 | 08177D2D1D46A3B000228592 /* PBXTargetDependency */,
172 | );
173 | name = TableFormTests;
174 | productName = TableFormTests;
175 | productReference = 08177D2B1D46A3B000228592 /* TableFormTests.xctest */;
176 | productType = "com.apple.product-type.bundle.unit-test";
177 | };
178 | 08177D351D46A3B000228592 /* TableFormUITests */ = {
179 | isa = PBXNativeTarget;
180 | buildConfigurationList = 08177D451D46A3B000228592 /* Build configuration list for PBXNativeTarget "TableFormUITests" */;
181 | buildPhases = (
182 | 08177D321D46A3B000228592 /* Sources */,
183 | 08177D331D46A3B000228592 /* Frameworks */,
184 | 08177D341D46A3B000228592 /* Resources */,
185 | );
186 | buildRules = (
187 | );
188 | dependencies = (
189 | 08177D381D46A3B000228592 /* PBXTargetDependency */,
190 | );
191 | name = TableFormUITests;
192 | productName = TableFormUITests;
193 | productReference = 08177D361D46A3B000228592 /* TableFormUITests.xctest */;
194 | productType = "com.apple.product-type.bundle.ui-testing";
195 | };
196 | /* End PBXNativeTarget section */
197 |
198 | /* Begin PBXProject section */
199 | 08177D141D46A3B000228592 /* Project object */ = {
200 | isa = PBXProject;
201 | attributes = {
202 | LastSwiftUpdateCheck = 0730;
203 | LastUpgradeCheck = 0930;
204 | ORGANIZATIONNAME = Gazolla;
205 | TargetAttributes = {
206 | 08177D1B1D46A3B000228592 = {
207 | CreatedOnToolsVersion = 7.3.1;
208 | DevelopmentTeam = MA5BADG5AW;
209 | LastSwiftMigration = 0900;
210 | };
211 | 08177D2A1D46A3B000228592 = {
212 | CreatedOnToolsVersion = 7.3.1;
213 | LastSwiftMigration = 0900;
214 | TestTargetID = 08177D1B1D46A3B000228592;
215 | };
216 | 08177D351D46A3B000228592 = {
217 | CreatedOnToolsVersion = 7.3.1;
218 | LastSwiftMigration = 0900;
219 | TestTargetID = 08177D1B1D46A3B000228592;
220 | };
221 | };
222 | };
223 | buildConfigurationList = 08177D171D46A3B000228592 /* Build configuration list for PBXProject "TableForm" */;
224 | compatibilityVersion = "Xcode 3.2";
225 | developmentRegion = English;
226 | hasScannedForEncodings = 0;
227 | knownRegions = (
228 | en,
229 | Base,
230 | );
231 | mainGroup = 08177D131D46A3B000228592;
232 | productRefGroup = 08177D1D1D46A3B000228592 /* Products */;
233 | projectDirPath = "";
234 | projectRoot = "";
235 | targets = (
236 | 08177D1B1D46A3B000228592 /* TableForm */,
237 | 08177D2A1D46A3B000228592 /* TableFormTests */,
238 | 08177D351D46A3B000228592 /* TableFormUITests */,
239 | );
240 | };
241 | /* End PBXProject section */
242 |
243 | /* Begin PBXResourcesBuildPhase section */
244 | 08177D1A1D46A3B000228592 /* Resources */ = {
245 | isa = PBXResourcesBuildPhase;
246 | buildActionMask = 2147483647;
247 | files = (
248 | 0860B2891F86D01E00D76378 /* README.md in Resources */,
249 | 08177D221D46A3B000228592 /* Assets.xcassets in Resources */,
250 | 08177D251D46A3B000228592 /* LaunchScreen.storyboard in Resources */,
251 | );
252 | runOnlyForDeploymentPostprocessing = 0;
253 | };
254 | 08177D291D46A3B000228592 /* Resources */ = {
255 | isa = PBXResourcesBuildPhase;
256 | buildActionMask = 2147483647;
257 | files = (
258 | );
259 | runOnlyForDeploymentPostprocessing = 0;
260 | };
261 | 08177D341D46A3B000228592 /* Resources */ = {
262 | isa = PBXResourcesBuildPhase;
263 | buildActionMask = 2147483647;
264 | files = (
265 | );
266 | runOnlyForDeploymentPostprocessing = 0;
267 | };
268 | /* End PBXResourcesBuildPhase section */
269 |
270 | /* Begin PBXSourcesBuildPhase section */
271 | 08177D181D46A3B000228592 /* Sources */ = {
272 | isa = PBXSourcesBuildPhase;
273 | buildActionMask = 2147483647;
274 | files = (
275 | 08284B191F8688FD00367E83 /* MyFormView.swift in Sources */,
276 | 0882883E1E738F1B00DDA1C6 /* FormView.swift in Sources */,
277 | 08177D201D46A3B000228592 /* AppDelegate.swift in Sources */,
278 | 08523E851F8969D8008D444D /* TableViewController.swift in Sources */,
279 | 08177D4B1D46DD3A00228592 /* FormCells.swift in Sources */,
280 | 08177D491D46A3BD00228592 /* FormViewController.swift in Sources */,
281 | );
282 | runOnlyForDeploymentPostprocessing = 0;
283 | };
284 | 08177D271D46A3B000228592 /* Sources */ = {
285 | isa = PBXSourcesBuildPhase;
286 | buildActionMask = 2147483647;
287 | files = (
288 | 08177D301D46A3B000228592 /* TableFormTests.swift in Sources */,
289 | );
290 | runOnlyForDeploymentPostprocessing = 0;
291 | };
292 | 08177D321D46A3B000228592 /* Sources */ = {
293 | isa = PBXSourcesBuildPhase;
294 | buildActionMask = 2147483647;
295 | files = (
296 | 08177D3B1D46A3B000228592 /* TableFormUITests.swift in Sources */,
297 | );
298 | runOnlyForDeploymentPostprocessing = 0;
299 | };
300 | /* End PBXSourcesBuildPhase section */
301 |
302 | /* Begin PBXTargetDependency section */
303 | 08177D2D1D46A3B000228592 /* PBXTargetDependency */ = {
304 | isa = PBXTargetDependency;
305 | target = 08177D1B1D46A3B000228592 /* TableForm */;
306 | targetProxy = 08177D2C1D46A3B000228592 /* PBXContainerItemProxy */;
307 | };
308 | 08177D381D46A3B000228592 /* PBXTargetDependency */ = {
309 | isa = PBXTargetDependency;
310 | target = 08177D1B1D46A3B000228592 /* TableForm */;
311 | targetProxy = 08177D371D46A3B000228592 /* PBXContainerItemProxy */;
312 | };
313 | /* End PBXTargetDependency section */
314 |
315 | /* Begin PBXVariantGroup section */
316 | 08177D231D46A3B000228592 /* LaunchScreen.storyboard */ = {
317 | isa = PBXVariantGroup;
318 | children = (
319 | 08177D241D46A3B000228592 /* Base */,
320 | );
321 | name = LaunchScreen.storyboard;
322 | sourceTree = "";
323 | };
324 | /* End PBXVariantGroup section */
325 |
326 | /* Begin XCBuildConfiguration section */
327 | 08177D3D1D46A3B000228592 /* Debug */ = {
328 | isa = XCBuildConfiguration;
329 | buildSettings = {
330 | ALWAYS_SEARCH_USER_PATHS = NO;
331 | CLANG_ANALYZER_NONNULL = YES;
332 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
333 | CLANG_CXX_LIBRARY = "libc++";
334 | CLANG_ENABLE_MODULES = YES;
335 | CLANG_ENABLE_OBJC_ARC = YES;
336 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
337 | CLANG_WARN_BOOL_CONVERSION = YES;
338 | CLANG_WARN_COMMA = YES;
339 | CLANG_WARN_CONSTANT_CONVERSION = YES;
340 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
341 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
342 | CLANG_WARN_EMPTY_BODY = YES;
343 | CLANG_WARN_ENUM_CONVERSION = YES;
344 | CLANG_WARN_INFINITE_RECURSION = YES;
345 | CLANG_WARN_INT_CONVERSION = YES;
346 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
347 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
348 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
349 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
350 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
351 | CLANG_WARN_STRICT_PROTOTYPES = YES;
352 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
353 | CLANG_WARN_UNREACHABLE_CODE = YES;
354 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
355 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
356 | COPY_PHASE_STRIP = NO;
357 | DEBUG_INFORMATION_FORMAT = dwarf;
358 | ENABLE_STRICT_OBJC_MSGSEND = YES;
359 | ENABLE_TESTABILITY = YES;
360 | GCC_C_LANGUAGE_STANDARD = gnu99;
361 | GCC_DYNAMIC_NO_PIC = NO;
362 | GCC_NO_COMMON_BLOCKS = YES;
363 | GCC_OPTIMIZATION_LEVEL = 0;
364 | GCC_PREPROCESSOR_DEFINITIONS = (
365 | "DEBUG=1",
366 | "$(inherited)",
367 | );
368 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
369 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
370 | GCC_WARN_UNDECLARED_SELECTOR = YES;
371 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
372 | GCC_WARN_UNUSED_FUNCTION = YES;
373 | GCC_WARN_UNUSED_VARIABLE = YES;
374 | IPHONEOS_DEPLOYMENT_TARGET = 11.0;
375 | MTL_ENABLE_DEBUG_INFO = YES;
376 | ONLY_ACTIVE_ARCH = YES;
377 | SDKROOT = iphoneos;
378 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
379 | TARGETED_DEVICE_FAMILY = "1,2";
380 | };
381 | name = Debug;
382 | };
383 | 08177D3E1D46A3B000228592 /* Release */ = {
384 | isa = XCBuildConfiguration;
385 | buildSettings = {
386 | ALWAYS_SEARCH_USER_PATHS = NO;
387 | CLANG_ANALYZER_NONNULL = YES;
388 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
389 | CLANG_CXX_LIBRARY = "libc++";
390 | CLANG_ENABLE_MODULES = YES;
391 | CLANG_ENABLE_OBJC_ARC = YES;
392 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
393 | CLANG_WARN_BOOL_CONVERSION = YES;
394 | CLANG_WARN_COMMA = YES;
395 | CLANG_WARN_CONSTANT_CONVERSION = YES;
396 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
397 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
398 | CLANG_WARN_EMPTY_BODY = YES;
399 | CLANG_WARN_ENUM_CONVERSION = YES;
400 | CLANG_WARN_INFINITE_RECURSION = YES;
401 | CLANG_WARN_INT_CONVERSION = YES;
402 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
403 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
404 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
405 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
406 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
407 | CLANG_WARN_STRICT_PROTOTYPES = YES;
408 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
409 | CLANG_WARN_UNREACHABLE_CODE = YES;
410 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
411 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
412 | COPY_PHASE_STRIP = NO;
413 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
414 | ENABLE_NS_ASSERTIONS = NO;
415 | ENABLE_STRICT_OBJC_MSGSEND = YES;
416 | GCC_C_LANGUAGE_STANDARD = gnu99;
417 | GCC_NO_COMMON_BLOCKS = YES;
418 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
419 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
420 | GCC_WARN_UNDECLARED_SELECTOR = YES;
421 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
422 | GCC_WARN_UNUSED_FUNCTION = YES;
423 | GCC_WARN_UNUSED_VARIABLE = YES;
424 | IPHONEOS_DEPLOYMENT_TARGET = 11.0;
425 | MTL_ENABLE_DEBUG_INFO = NO;
426 | SDKROOT = iphoneos;
427 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
428 | TARGETED_DEVICE_FAMILY = "1,2";
429 | VALIDATE_PRODUCT = YES;
430 | };
431 | name = Release;
432 | };
433 | 08177D401D46A3B000228592 /* Debug */ = {
434 | isa = XCBuildConfiguration;
435 | buildSettings = {
436 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
437 | CODE_SIGN_IDENTITY = "iPhone Developer";
438 | INFOPLIST_FILE = TableForm/Info.plist;
439 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
440 | PRODUCT_BUNDLE_IDENTIFIER = com.gazapps.TableForm;
441 | PRODUCT_NAME = "$(TARGET_NAME)";
442 | SWIFT_SWIFT3_OBJC_INFERENCE = Default;
443 | SWIFT_VERSION = 4.0;
444 | };
445 | name = Debug;
446 | };
447 | 08177D411D46A3B000228592 /* Release */ = {
448 | isa = XCBuildConfiguration;
449 | buildSettings = {
450 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
451 | CODE_SIGN_IDENTITY = "iPhone Developer";
452 | INFOPLIST_FILE = TableForm/Info.plist;
453 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
454 | PRODUCT_BUNDLE_IDENTIFIER = com.gazapps.TableForm;
455 | PRODUCT_NAME = "$(TARGET_NAME)";
456 | SWIFT_SWIFT3_OBJC_INFERENCE = Default;
457 | SWIFT_VERSION = 4.0;
458 | };
459 | name = Release;
460 | };
461 | 08177D431D46A3B000228592 /* Debug */ = {
462 | isa = XCBuildConfiguration;
463 | buildSettings = {
464 | BUNDLE_LOADER = "$(TEST_HOST)";
465 | INFOPLIST_FILE = TableFormTests/Info.plist;
466 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
467 | PRODUCT_BUNDLE_IDENTIFIER = com.gazapps.TableFormTests;
468 | PRODUCT_NAME = "$(TARGET_NAME)";
469 | SWIFT_SWIFT3_OBJC_INFERENCE = On;
470 | SWIFT_VERSION = 4.0;
471 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/TableForm.app/TableForm";
472 | };
473 | name = Debug;
474 | };
475 | 08177D441D46A3B000228592 /* Release */ = {
476 | isa = XCBuildConfiguration;
477 | buildSettings = {
478 | BUNDLE_LOADER = "$(TEST_HOST)";
479 | INFOPLIST_FILE = TableFormTests/Info.plist;
480 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
481 | PRODUCT_BUNDLE_IDENTIFIER = com.gazapps.TableFormTests;
482 | PRODUCT_NAME = "$(TARGET_NAME)";
483 | SWIFT_SWIFT3_OBJC_INFERENCE = On;
484 | SWIFT_VERSION = 4.0;
485 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/TableForm.app/TableForm";
486 | };
487 | name = Release;
488 | };
489 | 08177D461D46A3B000228592 /* Debug */ = {
490 | isa = XCBuildConfiguration;
491 | buildSettings = {
492 | INFOPLIST_FILE = TableFormUITests/Info.plist;
493 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
494 | PRODUCT_BUNDLE_IDENTIFIER = com.gazapps.TableFormUITests;
495 | PRODUCT_NAME = "$(TARGET_NAME)";
496 | SWIFT_SWIFT3_OBJC_INFERENCE = On;
497 | SWIFT_VERSION = 4.0;
498 | TEST_TARGET_NAME = TableForm;
499 | };
500 | name = Debug;
501 | };
502 | 08177D471D46A3B000228592 /* Release */ = {
503 | isa = XCBuildConfiguration;
504 | buildSettings = {
505 | INFOPLIST_FILE = TableFormUITests/Info.plist;
506 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
507 | PRODUCT_BUNDLE_IDENTIFIER = com.gazapps.TableFormUITests;
508 | PRODUCT_NAME = "$(TARGET_NAME)";
509 | SWIFT_SWIFT3_OBJC_INFERENCE = On;
510 | SWIFT_VERSION = 4.0;
511 | TEST_TARGET_NAME = TableForm;
512 | };
513 | name = Release;
514 | };
515 | /* End XCBuildConfiguration section */
516 |
517 | /* Begin XCConfigurationList section */
518 | 08177D171D46A3B000228592 /* Build configuration list for PBXProject "TableForm" */ = {
519 | isa = XCConfigurationList;
520 | buildConfigurations = (
521 | 08177D3D1D46A3B000228592 /* Debug */,
522 | 08177D3E1D46A3B000228592 /* Release */,
523 | );
524 | defaultConfigurationIsVisible = 0;
525 | defaultConfigurationName = Release;
526 | };
527 | 08177D3F1D46A3B000228592 /* Build configuration list for PBXNativeTarget "TableForm" */ = {
528 | isa = XCConfigurationList;
529 | buildConfigurations = (
530 | 08177D401D46A3B000228592 /* Debug */,
531 | 08177D411D46A3B000228592 /* Release */,
532 | );
533 | defaultConfigurationIsVisible = 0;
534 | defaultConfigurationName = Release;
535 | };
536 | 08177D421D46A3B000228592 /* Build configuration list for PBXNativeTarget "TableFormTests" */ = {
537 | isa = XCConfigurationList;
538 | buildConfigurations = (
539 | 08177D431D46A3B000228592 /* Debug */,
540 | 08177D441D46A3B000228592 /* Release */,
541 | );
542 | defaultConfigurationIsVisible = 0;
543 | defaultConfigurationName = Release;
544 | };
545 | 08177D451D46A3B000228592 /* Build configuration list for PBXNativeTarget "TableFormUITests" */ = {
546 | isa = XCConfigurationList;
547 | buildConfigurations = (
548 | 08177D461D46A3B000228592 /* Debug */,
549 | 08177D471D46A3B000228592 /* Release */,
550 | );
551 | defaultConfigurationIsVisible = 0;
552 | defaultConfigurationName = Release;
553 | };
554 | /* End XCConfigurationList section */
555 | };
556 | rootObject = 08177D141D46A3B000228592 /* Project object */;
557 | }
558 |
--------------------------------------------------------------------------------
/TableForm/FormCells.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TextCell.swift
3 | // TableForm
4 | //
5 | // Created by Gazolla on 05/10/17.
6 | // Copyright © 2016 Gazolla. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import QuartzCore
11 |
12 | open class FormCell:UITableViewCell {
13 | var name:String?
14 |
15 | lazy var space:UIView = {
16 | let v = UIView()
17 | v.widthAnchor.constraint(equalToConstant: self.bounds.width*0.001).isActive = true
18 | return v
19 | }()
20 |
21 | override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
22 | super.init(style: .default, reuseIdentifier: reuseIdentifier)
23 | self.setup()
24 | }
25 |
26 | required public init?(coder aDecoder: NSCoder) {
27 | super.init(coder: aDecoder)
28 | self.setup()
29 | }
30 |
31 | override open func awakeFromNib() {
32 | super.awakeFromNib()
33 | self.setup()
34 | }
35 |
36 | func setup() {
37 | self.textLabel?.font = UIFont.preferredFont(forTextStyle: UIFontTextStyle.body)
38 | self.textLabel?.textColor = .black
39 | }
40 |
41 | func setCellData(key: String, value: AnyObject){ }
42 |
43 | func getCellData()-> (key: String, value: AnyObject){
44 | let key = ""
45 | let value = "" as AnyObject
46 | return(key, value)
47 | }
48 |
49 | open override func layoutSubviews() {
50 | super.layoutSubviews()
51 | if self.tag == 999 { //botton cell
52 | layer.shadowColor = UIColor.lightGray.cgColor
53 | layer.shadowOffset = CGSize(width: 0, height: 2.0)
54 | layer.shadowRadius = 2.0
55 | layer.shadowOpacity = 1.0
56 | layer.masksToBounds = false
57 | layer.shadowPath = UIBezierPath(roundedRect: bounds, cornerRadius: contentView.layer.cornerRadius).cgPath
58 | }
59 | }
60 |
61 | }
62 |
63 | open class TextViewCell: FormCell, UITextViewDelegate {
64 |
65 | var textView = UITextView()
66 |
67 | override func setup() {
68 | super.setup()
69 |
70 | self.contentView.viewWithTag(3)?.removeFromSuperview()
71 | textView.autocorrectionType = .no
72 | textView.autocapitalizationType = .none
73 | self.textView.delegate = self
74 | self.textView.tag = 3
75 | self.textView.translatesAutoresizingMaskIntoConstraints = false
76 | self.addSubview(self.textView)
77 |
78 | addConstraintsWithFormat("V:|-3-[v0]-3-|", views:self.textView)
79 | addConstraintsWithFormat("H:|-100-[v0]-5-|", views:self.textView)
80 |
81 | self.textView.textAlignment = .left
82 | }
83 |
84 | override open func touchesBegan(_ touches: Set, with event: UIEvent?) {
85 | self.textView.becomeFirstResponder()
86 | }
87 |
88 | public func textViewDidEndEditing(_ textView: UITextView) {
89 | textView.resignFirstResponder()
90 | }
91 |
92 | override func setCellData(key: String, value: AnyObject){
93 | self.textView.text! = value as! String
94 | }
95 |
96 | override func getCellData()-> (key: String, value: AnyObject){
97 | let key = self.name!
98 | let value = self.textView.text as AnyObject
99 | return(key, value)
100 | }
101 |
102 | public func textViewShouldBeginEditing(_ textView: UITextView) -> Bool {
103 | var view = self.superview
104 | while (view != nil && view!.isKind(of: UITableView.self) == false) {
105 | view = view!.superview
106 | }
107 | let tableView = view as? UITableView
108 |
109 | let txtFieldPosition = textView.convert(textView.bounds.origin, to: tableView)
110 | let indexPath = tableView?.indexPathForRow(at: txtFieldPosition)
111 | if indexPath != nil {
112 | tableView?.scrollToRow(at: indexPath!, at: .top, animated: true)
113 | }
114 | return true
115 | }
116 | }
117 |
118 | open class ImageCell: FormCell, UITextViewDelegate {
119 |
120 | var imgView = UIImageView()
121 | var fileName:String = ""
122 |
123 | override func setup() {
124 | super.setup()
125 | self.contentView.viewWithTag(3)?.removeFromSuperview()
126 | imgView.backgroundColor = .white
127 | imgView.contentMode = .scaleAspectFit
128 | imgView.translatesAutoresizingMaskIntoConstraints = false
129 | self.addSubview(self.imgView)
130 |
131 | addConstraintsWithFormat("V:|-3-[v0]-3-|", views:self.imgView)
132 | addConstraintsWithFormat("H:|-100-[v0]-5-|", views:self.imgView)
133 | }
134 |
135 |
136 | override func setCellData(key: String, value: AnyObject){
137 | fileName = value as! String
138 | imgView.image = UIImage(named: fileName)
139 | }
140 |
141 | override func getCellData()-> (key: String, value: AnyObject){
142 | let key = self.name!
143 | let value = fileName as AnyObject
144 | return(key, value)
145 | }
146 |
147 | }
148 |
149 | open class TextCell: FormCell, UITextFieldDelegate {
150 |
151 | var textField:UITextField = {
152 | let tf = UITextField()
153 | tf.font = UIFont.preferredFont(forTextStyle: UIFontTextStyle.body)
154 | tf.autocorrectionType = .no
155 | tf.autocapitalizationType = .none
156 | tf.tag = 3
157 | tf.translatesAutoresizingMaskIntoConstraints = false
158 | tf.textAlignment = .left
159 | tf.contentVerticalAlignment = .center
160 | return tf
161 | }()
162 |
163 | override func setup() {
164 | super.setup()
165 | contentView.viewWithTag(3)?.removeFromSuperview()
166 | textField.delegate = self
167 | addSubview(textField)
168 |
169 | textField.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true
170 | textField.rightAnchor.constraint(equalTo: self.rightAnchor, constant:-5).isActive = true
171 | textField.leftAnchor.constraint(equalTo: self.leftAnchor, constant:115).isActive = true
172 | textField.heightAnchor.constraint(equalTo: self.heightAnchor).isActive = true
173 |
174 | }
175 |
176 | override open func touchesBegan(_ touches: Set, with event: UIEvent?) {
177 | self.textField.becomeFirstResponder()
178 | }
179 |
180 | open func textFieldShouldReturn(_ textField: UITextField) -> Bool {
181 | print("textFieldShouldReturn")
182 | textField.resignFirstResponder()
183 | return true
184 | }
185 |
186 | override func setCellData(key: String, value: AnyObject){
187 | if let strValue = value as? String {
188 | self.textField.text! = strValue
189 | }
190 | }
191 |
192 | override func getCellData()-> (key: String, value: AnyObject){
193 | let key = self.name!
194 | let value = self.textField.text as AnyObject
195 | return(key, value)
196 | }
197 |
198 | public func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
199 | var view = self.superview
200 | while (view != nil && view!.isKind(of: UITableView.self) == false) {
201 | view = view!.superview
202 | }
203 | let tableView = view as? UITableView
204 |
205 | let txtFieldPosition = textField.convert(textField.bounds.origin, to: tableView)
206 | let indexPath = tableView?.indexPathForRow(at: txtFieldPosition)
207 | if indexPath != nil {
208 | tableView?.scrollToRow(at: indexPath!, at: .top, animated: true)
209 | }
210 | return true
211 | }
212 |
213 |
214 | }
215 |
216 | open class NumberCell: FormCell, UITextFieldDelegate {
217 |
218 | lazy var numberFormatted:UITextField = {
219 | let nf = UITextField()
220 | nf.delegate = self
221 | nf.tag = 3
222 | nf.translatesAutoresizingMaskIntoConstraints = false
223 | nf.placeholder = "0.00"
224 | nf.font = UIFont.preferredFont(forTextStyle: UIFontTextStyle.title1)
225 | nf.autocorrectionType = UITextAutocorrectionType.no
226 | nf.keyboardType = UIKeyboardType.numberPad
227 | nf.returnKeyType = UIReturnKeyType.done
228 | nf.clearButtonMode = UITextFieldViewMode.whileEditing
229 | nf.contentVerticalAlignment = UIControlContentVerticalAlignment.center
230 | nf.textAlignment = NSTextAlignment.center
231 | return nf
232 | }()
233 |
234 | let formatter: NumberFormatter = {
235 | let formatter = NumberFormatter()
236 | formatter.numberStyle = .currency
237 | formatter.currencySymbol = ""
238 | formatter.maximumFractionDigits = 2
239 | formatter.minimumFractionDigits = 2
240 | return formatter
241 | }()
242 |
243 | var amountTypedString = ""
244 |
245 | override func setup() {
246 | super.setup()
247 | self.addSubview(numberFormatted)
248 |
249 | numberFormatted.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true
250 | numberFormatted.rightAnchor.constraint(equalTo: self.rightAnchor, constant:-5).isActive = true
251 | numberFormatted.leftAnchor.constraint(equalTo: self.leftAnchor, constant:115).isActive = true
252 | numberFormatted.heightAnchor.constraint(equalTo: self.heightAnchor).isActive = true
253 | }
254 |
255 | override open func touchesBegan(_ touches: Set, with event: UIEvent?) {
256 | numberFormatted.becomeFirstResponder()
257 | }
258 |
259 | open func textFieldShouldReturn(_ textField: UITextField) -> Bool {
260 | textField.resignFirstResponder()
261 | return true
262 | }
263 |
264 | public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
265 | // print("amountTypedString:\(amountTypedString)")
266 | if string.count > 0 {
267 | print(string)
268 | amountTypedString += string
269 | print(amountTypedString)
270 | let decNumber = NSDecimalNumber(value: Float(amountTypedString)! as Float).multiplying(by: 0.01)
271 | print(decNumber)
272 | let newString = formatter.string(from: decNumber)!
273 | print(newString)
274 | numberFormatted.text = newString
275 | } else {
276 | amountTypedString = String(amountTypedString.dropLast())
277 | if amountTypedString.count > 0 {
278 | let decNumber = NSDecimalNumber(value: Float(amountTypedString)! as Float).multiplying(by: 0.01)
279 | let newString = formatter.string(from: decNumber)!
280 | numberFormatted.text = newString
281 | } else {
282 | numberFormatted.text = "0.00"
283 | }
284 |
285 | }
286 | return false
287 | }
288 |
289 | public func textFieldShouldClear(_ textField: UITextField) -> Bool {
290 | amountTypedString = ""
291 | return true
292 | }
293 |
294 | override func setCellData(key: String, value: AnyObject){
295 | var strValue = ""
296 | if value is String{
297 | strValue = value as! String
298 | } else if value is Double {
299 | strValue = String(format: "%\(0.2)f", (value as! Double))
300 | // strValue = "\(value)"
301 | }
302 | numberFormatted.text! = strValue
303 | let charsNotToBeTrimmed = (0...9).map{String($0)}
304 | for i in strValue{
305 | if !charsNotToBeTrimmed.contains(String(i)){
306 | strValue = strValue.replacingOccurrences(of: String(i), with: "")
307 | }
308 | }
309 | // print("filtered: \(strValue)")
310 | amountTypedString = strValue
311 | // print("amountTypedString:\(amountTypedString)")
312 | }
313 |
314 | override func getCellData()-> (key: String, value: AnyObject){
315 | let key = self.name!
316 | let value = numberFormatted.text as AnyObject
317 | return(key, value)
318 | }
319 |
320 |
321 | }
322 |
323 | open class IntCell : TextCell {
324 |
325 | override func setup() {
326 | super.setup()
327 | textField.textAlignment = .right
328 | textField.autocorrectionType = .default
329 | textField.autocapitalizationType = .none
330 | textField.keyboardType = .numberPad
331 | }
332 |
333 | override func setCellData(key: String, value: AnyObject){
334 | let nf = NumberFormatter()
335 | self.textField.text! = nf.string(from: value as! NSNumber)!
336 | }
337 |
338 | }
339 |
340 | open class PhoneCell : TextCell {
341 |
342 | override func setup() {
343 | super.setup()
344 | textField.keyboardType = .phonePad
345 | }
346 | }
347 |
348 | open class NameCell : TextCell {
349 |
350 | open override func setup() {
351 | super.setup()
352 | textField.autocorrectionType = .no
353 | textField.autocapitalizationType = .words
354 | textField.keyboardType = .asciiCapable
355 | }
356 |
357 | override open func textFieldShouldReturn(_ textField: UITextField) -> Bool {
358 | print("textFieldShouldReturn")
359 | textField.resignFirstResponder()
360 | return true
361 | }
362 | }
363 |
364 | open class EmailCell : TextCell {
365 |
366 | open override func setup() {
367 | super.setup()
368 | textField.autocorrectionType = .no
369 | textField.autocapitalizationType = .none
370 | textField.keyboardType = .emailAddress
371 | }
372 | }
373 |
374 | open class PasswordCell : TextCell {
375 |
376 | open override func setup() {
377 | super.setup()
378 | textField.autocorrectionType = .no
379 | textField.autocapitalizationType = .none
380 | textField.keyboardType = .asciiCapable
381 | textField.isSecureTextEntry = true
382 | }
383 | }
384 |
385 | open class DecimalCell : TextCell {
386 |
387 | open override func setup() {
388 | super.setup()
389 | textField.autocorrectionType = .no
390 | textField.keyboardType = .decimalPad
391 | }
392 | }
393 |
394 | open class URLCell : TextCell {
395 |
396 | open override func setup() {
397 | super.setup()
398 | textField.autocorrectionType = .no
399 | textField.autocapitalizationType = .none
400 | textField.keyboardType = .URL
401 | }
402 | }
403 |
404 | open class TwitterCell : TextCell {
405 |
406 | open override func setup() {
407 | super.setup()
408 | textField.autocorrectionType = .no
409 | textField.autocapitalizationType = .none
410 | textField.keyboardType = .twitter
411 | }
412 | }
413 |
414 | open class AccountCell : TextCell {
415 |
416 | open override func setup() {
417 | super.setup()
418 | textField.autocorrectionType = .no
419 | textField.autocapitalizationType = .none
420 | textField.keyboardType = .asciiCapable
421 | }
422 | }
423 |
424 | open class ZipCodeCell : TextCell {
425 |
426 | open override func setup() {
427 | super.setup()
428 | textField.autocorrectionType = .no
429 | textField.autocapitalizationType = .allCharacters
430 | textField.keyboardType = .numbersAndPunctuation
431 | }
432 | }
433 |
434 | open class DateCell : TextCell {
435 |
436 | var update:((_ date:Date)->())?
437 |
438 | var datePicker = UIDatePicker()
439 | var formatter:DateFormatter {
440 | let f = DateFormatter()
441 | f.dateStyle = .medium
442 | return f
443 | }
444 |
445 | override func setup() {
446 | super.setup()
447 |
448 | self.textField.textAlignment = .right
449 |
450 | accessoryType = .none
451 | editingAccessoryType = .none
452 | datePicker.datePickerMode = UIDatePickerMode.date
453 | self.textField.inputView = datePicker
454 | datePicker.addTarget(self, action: #selector(DateCell.datePickerValueChanged(_:)), for: .valueChanged)
455 | }
456 |
457 | deinit {
458 | datePicker.removeTarget(self, action: nil, for: .allEvents)
459 | }
460 |
461 | @objc func datePickerValueChanged(_ sender: UIDatePicker){
462 | self.textField.text = formatter.string(from: sender.date)
463 | // self.update?(sender.date)
464 | }
465 |
466 | override func setCellData(key: String, value: AnyObject){
467 | if let dateValue = value as? Date {
468 | self.datePicker.date = dateValue
469 | self.textField.text! = self.formatter.string(from: dateValue)
470 | }
471 | }
472 |
473 | override func getCellData()-> (key: String, value: AnyObject){
474 | let key = self.name!
475 | let value = self.textField.text as AnyObject
476 | return(key, value)
477 | }
478 | }
479 |
480 | open class ButtonCell: FormCell, UITextFieldDelegate {
481 |
482 | override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
483 | super.init(style: style, reuseIdentifier: reuseIdentifier)
484 | self.setup()
485 | }
486 |
487 | required public init?(coder aDecoder: NSCoder) {
488 | super.init(coder: aDecoder)
489 | self.setup()
490 | }
491 |
492 | override open func awakeFromNib() {
493 | super.awakeFromNib()
494 | self.setup()
495 | }
496 |
497 | override func setup() {
498 | textLabel?.textColor = tintColor
499 | selectionStyle = .default
500 | accessoryType = .none
501 | editingAccessoryType = accessoryType
502 | textLabel?.textAlignment = .center
503 | textLabel?.font = UIFont.preferredFont(forTextStyle: UIFontTextStyle.title1)
504 | }
505 | }
506 |
507 |
508 | open class LinkCell : FormCell {
509 |
510 | lazy var valueLabel:UILabel = {
511 | let l = UILabel()
512 | l.translatesAutoresizingMaskIntoConstraints = false
513 | l.baselineAdjustment = .alignCenters
514 | l.textAlignment = .right
515 | l.font = UIFont.preferredFont(forTextStyle: UIFontTextStyle.body)
516 | l.textColor = UIColor.black
517 | l.backgroundColor = UIColor.clear
518 | return l
519 | }()
520 |
521 | override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
522 | super.init(style:.value1, reuseIdentifier: reuseIdentifier)
523 | self.setup()
524 | textLabel?.textColor = .black
525 | }
526 |
527 | required public init?(coder aDecoder: NSCoder) {
528 | super.init(coder: aDecoder)
529 | self.setup()
530 | }
531 |
532 | override open func awakeFromNib() {
533 | super.awakeFromNib()
534 | self.setup()
535 | }
536 |
537 | override func setup() {
538 | super.setup()
539 | accessoryType = .disclosureIndicator
540 | editingAccessoryType = .none
541 | addSubview(valueLabel)
542 | }
543 |
544 | open override func updateConstraints() {
545 | super.updateConstraints()
546 | let margins = self.layoutMarginsGuide
547 | valueLabel.heightAnchor.constraint(equalTo: margins.heightAnchor, multiplier: 0.8).isActive = true
548 | valueLabel.centerYAnchor.constraint(equalTo: margins.centerYAnchor).isActive = true
549 | valueLabel.rightAnchor.constraint(equalTo: margins.rightAnchor, constant:-40).isActive = true
550 | valueLabel.widthAnchor.constraint(equalTo: margins.widthAnchor, multiplier: 0.5).isActive = true
551 | }
552 |
553 | open override func prepareForReuse() {
554 | super.prepareForReuse()
555 | valueLabel.text = ""
556 | }
557 |
558 | override func setCellData(key: String, value: AnyObject){
559 | if let strValue = value as? String {
560 | valueLabel.text = strValue
561 | }
562 | }
563 |
564 | override func getCellData()-> (key: String, value: AnyObject){
565 | let key = self.name!
566 | let value = valueLabel.text as AnyObject
567 | return(key, value)
568 | }
569 |
570 | }
571 |
572 |
573 | open class SliderCell: FormCell {
574 |
575 | lazy var slider:UISlider = {
576 | let s = UISlider()
577 | s.minimumValue = 0
578 | s.maximumValue = 100
579 | s.isContinuous = true
580 | s.tintColor = UIColor.green
581 | s.addTarget(self, action: #selector(sliderValueDidChange(_:)), for: .valueChanged)
582 | s.widthAnchor.constraint(equalToConstant: self.bounds.width*0.9).isActive = true
583 | return s
584 | }()
585 |
586 | lazy var titleLabel:UILabel = {
587 | let l = self.getLabel()
588 | return l
589 | }()
590 |
591 | lazy var minLabel:UILabel = {
592 | let l = self.getLabel()
593 | return l
594 | }()
595 |
596 | lazy var maxLabel:UILabel = {
597 | let l = self.getLabel()
598 | return l
599 | }()
600 |
601 | lazy var valueLabel:UILabel = {
602 | let l = self.getLabel()
603 | l.textColor = UIColor.lightGray
604 | l.font = UIFont.preferredFont(forTextStyle: UIFontTextStyle.subheadline)
605 | l.text = "00 %"
606 | return l
607 | }()
608 |
609 | lazy var sliderStack:UIStackView = {
610 | let s = UIStackView()
611 | s.axis = .horizontal
612 | s.distribution = .fillProportionally
613 | s.alignment = .fill
614 | s.spacing = 0
615 | s.autoresizingMask = [.flexibleWidth, .flexibleHeight]
616 | s.addArrangedSubview(UIView())
617 | s.addArrangedSubview(self.minLabel)
618 | s.addArrangedSubview(UIView())
619 | s.addArrangedSubview(self.slider)
620 | s.addArrangedSubview(UIView())
621 | s.addArrangedSubview(self.maxLabel)
622 | s.addArrangedSubview(UIView())
623 | return s
624 | }()
625 |
626 |
627 | lazy var mainStack:UIStackView = {
628 | print("main")
629 | let s = UIStackView(frame: self.bounds)
630 | s.axis = .vertical
631 | s.distribution = .fill
632 | s.alignment = .fill
633 | s.spacing = 0
634 | s.autoresizingMask = [.flexibleWidth, .flexibleHeight]
635 | s.addArrangedSubview(self.titleLabel)
636 | s.addArrangedSubview(self.sliderStack)
637 | s.addArrangedSubview(self.valueLabel)
638 | return s
639 | }()
640 |
641 | override func setup() {
642 | self.textLabel?.textColor = .clear
643 | self.addSubview(self.mainStack)
644 | }
645 |
646 | override open func layoutSubviews() {
647 | super.layoutSubviews()
648 | self.titleLabel.text = self.textLabel?.text
649 | self.minLabel.text = " \(String(Int(self.slider.minimumValue))) % "
650 | self.maxLabel.text = " \(String(Int(self.slider.maximumValue))) %"
651 | }
652 |
653 |
654 | @objc func sliderValueDidChange(_ sender:UISlider!){
655 | self.valueLabel.text = "\(Int(sender.value)) % "
656 | }
657 |
658 |
659 | override func setCellData(key: String, value: AnyObject){
660 | if let v = value.floatValue {
661 | self.slider.value = v
662 | self.valueLabel.text = "\(Int(v)) % "
663 | }
664 | }
665 |
666 | override func getCellData()-> (key: String, value: AnyObject){
667 | let key = self.name!
668 | let value = Int(self.slider.value) as AnyObject
669 | return(key, value)
670 | }
671 |
672 | func getLabel()->UILabel{
673 | let l = UILabel()
674 | l.textAlignment = .center
675 | l.font = UIFont.preferredFont(forTextStyle: UIFontTextStyle.caption1)
676 | l.textColor = UIColor.black
677 | l.backgroundColor = UIColor.clear
678 | return l
679 | }
680 | }
681 |
682 | open class SwitchCell:FormCell {
683 |
684 | lazy var switcher:UISwitch = {
685 | let s = UISwitch()
686 | s.addTarget(self, action: #selector(switchDidChange(_:)), for: .valueChanged)
687 | return s
688 | }()
689 |
690 | @objc func switchDidChange(_ sender:UISwitch!){
691 |
692 | }
693 |
694 | lazy var switchStack:UIStackView = {
695 | let s = UIStackView(frame: self.bounds)
696 | s.axis = .horizontal
697 | s.distribution = .fill
698 | s.alignment = .center
699 | s.spacing = 5
700 | s.autoresizingMask = [.flexibleWidth, .flexibleHeight]
701 | s.addArrangedSubview(UIView())
702 | s.addArrangedSubview(self.switcher)
703 | s.addArrangedSubview(self.space)
704 | return s
705 | }()
706 |
707 |
708 | override func setup() {
709 | self.textLabel?.font = UIFont.preferredFont(forTextStyle: UIFontTextStyle.caption1)
710 | self.addSubview(self.switchStack)
711 | }
712 |
713 | override func setCellData(key: String, value: AnyObject){
714 | let boolValue = value as! Bool
715 | self.switcher.isOn = boolValue
716 | }
717 |
718 | override func getCellData()-> (key: String, value: AnyObject){
719 | let key = self.name!
720 | let value = self.switcher.isOn as AnyObject
721 | return(key, value)
722 | }
723 | }
724 |
725 | open class StepperCell:FormCell {
726 |
727 | lazy var stepper:UIStepper = {
728 | let s = UIStepper()
729 | s.addTarget(self, action: #selector(stepperDidChange(_:)), for: .valueChanged)
730 | return s
731 | }()
732 |
733 | lazy var valueLabel:UILabel = {
734 | let l = UILabel()
735 | l.textAlignment = .center
736 | l.textColor = UIColor.black
737 | l.backgroundColor = UIColor.clear
738 | return l
739 | }()
740 |
741 | @objc func stepperDidChange(_ sender:UIStepper!){
742 | self.valueLabel.text = "\(Int(sender.value))"
743 | }
744 |
745 | lazy var switchStack:UIStackView = {
746 | let s = UIStackView(frame: self.bounds)
747 | s.axis = .horizontal
748 | s.distribution = .fill
749 | s.alignment = .center
750 | s.spacing = 5
751 | s.autoresizingMask = [.flexibleWidth, .flexibleHeight]
752 | s.addArrangedSubview(UIView())
753 | s.addArrangedSubview(self.valueLabel)
754 | s.addArrangedSubview(self.stepper)
755 | s.addArrangedSubview(self.space)
756 | return s
757 | }()
758 |
759 | override func setup() {
760 | self.textLabel?.font = UIFont.preferredFont(forTextStyle: UIFontTextStyle.caption1)
761 | self.addSubview(self.switchStack)
762 | }
763 |
764 | override func setCellData(key: String, value: AnyObject){
765 | if let dblValue = value.int64Value {
766 | self.valueLabel.text = "\(Int(dblValue))"
767 | self.stepper.value = Double(dblValue)
768 | }
769 | }
770 |
771 | override func getCellData()-> (key: String, value: AnyObject){
772 | let key = self.name!
773 | let value = self.stepper.value as AnyObject
774 | return(key, value)
775 | }
776 | }
777 |
778 | extension UIView{
779 | func addConstraintsWithFormat(_ format:String, views:UIView...){
780 | var viewsDictionary = [String:UIView]()
781 | for (index, view) in views.enumerated(){
782 | let key = "v\(index)"
783 | viewsDictionary[key]=view
784 | }
785 | addConstraints(NSLayoutConstraint.constraints(withVisualFormat: format, options: .alignAllLastBaseline, metrics: nil, views: viewsDictionary))
786 | }
787 | }
788 |
789 |
--------------------------------------------------------------------------------