SHARE
TWEET

Untitled

a guest Sep 19th, 2019 96 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import Foundation
  2. import UIKit
  3.  
  4. enum FormCellType {
  5.     case textField(data: TextFieldFormCellData)
  6.     case datePicker(data: DatePickerFormCellData)
  7.     case disclosure(image: UIImage?, placeholder: String, text: String, action: () -> Void)
  8. }
  9.  
  10. struct FormCellSection {
  11.     let title: String
  12.     let items: [FormCellType]
  13. }
  14.  
  15. protocol FormManagerDelegate: class {
  16.     var tableView: UITableView { get }
  17. }
  18.  
  19. final class FormManager: NSObject {
  20.  
  21.     weak var delegate: FormManagerDelegate? { didSet {
  22.         setUpTableView()
  23.     }}
  24.  
  25.     private var cells: [FormCellSection] = []
  26.  
  27.     private var currentlyShownDatePickerIndexPath: IndexPath?
  28.     private var lastSelectedInlineTextfieldCell: InlineTextFieldTableViewCell?
  29.  
  30.     private let dateFormatter = DateFormatter()
  31.  
  32.     func loadCells(data: [FormCellSection]) {
  33.         cells = data
  34.         delegate?.tableView.reloadData()
  35.     }
  36.  
  37.     private func setUpTableView() {
  38.         delegate?.tableView.register(UITableViewCell.self, forCellReuseIdentifier: UITableViewCell.defaultCellReuseIdentifier)
  39.         delegate?.tableView.register(InlineDatePickerTableViewCell.self, forCellReuseIdentifier: InlineDatePickerTableViewCell.defaultCellReuseIdentifier)
  40.         delegate?.tableView.register(InlineTextFieldTableViewCell.self, forCellReuseIdentifier: InlineTextFieldTableViewCell.defaultCellReuseIdentifier)
  41.         delegate?.tableView.register(RightValueTableViewCell.self, forCellReuseIdentifier: RightValueTableViewCell.defaultCellReuseIdentifier)
  42.     }
  43.  
  44.     private func indexPathToInsertDatePicker(indexPath: IndexPath) -> IndexPath {
  45.         if let datePickerIndexPath = currentlyShownDatePickerIndexPath, datePickerIndexPath.row < indexPath.row {
  46.             return indexPath
  47.         } else {
  48.             return IndexPath(row: indexPath.row + 1, section: indexPath.section)
  49.         }
  50.     }
  51.  
  52.     private func cellTypeFor(indexPath: IndexPath) -> FormCellType {
  53.         let section = cells[indexPath.section]
  54.         var row = indexPath.row
  55.         if let pickerIndexPath = currentlyShownDatePickerIndexPath, pickerIndexPath.section == indexPath.section {
  56.             if pickerIndexPath.row <= indexPath.row {
  57.                 row = indexPath.row - 1
  58.             }
  59.         }
  60.         let data = section.items
  61.         return data[row]
  62.     }
  63. }
  64.  
  65. extension FormManager: UITableViewDataSource {
  66.     func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
  67.         let data = cells[section].items
  68.         if currentlyShownDatePickerIndexPath?.section == section {
  69.             return data.count + 1
  70.         } else {
  71.             return data.count
  72.         }
  73.     }
  74.  
  75.     func numberOfSections(in tableView: UITableView) -> Int {
  76.         return cells.count
  77.     }
  78.  
  79.     func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  80.  
  81.         if currentlyShownDatePickerIndexPath == indexPath {
  82.             let cell = tableView.dequeueReusableCell(withIdentifier: InlineDatePickerTableViewCell.defaultCellReuseIdentifier, for: indexPath) as! InlineDatePickerTableViewCell
  83.             cell.indexPath = indexPath
  84.             cell.delegate = self
  85.             let cellType = cellTypeFor(indexPath: indexPath)
  86.             if case FormCellType.datePicker(let data) = cellType {
  87.                 cell.updateCell(date: data.date, datePickerMode: data.datePickerMode, indexPath: indexPath)
  88.             }
  89.             return cell
  90.         }
  91.        
  92.         let cellData = cellTypeFor(indexPath: indexPath)
  93.  
  94.         switch cellData {
  95.         case .textField(let data):
  96.             let cell = tableView.dequeueReusableCell(withIdentifier: InlineTextFieldTableViewCell.defaultCellReuseIdentifier, for: indexPath) as! InlineTextFieldTableViewCell
  97.             cell.bind(to: data)
  98.             cell.selectionStyle = .none
  99.             return cell
  100.         case .datePicker(let data):
  101.             let cell = tableView.dequeueReusableCell(withIdentifier: RightValueTableViewCell.defaultCellReuseIdentifier, for: indexPath)
  102.            
  103.             dateFormatter.dateFormat = data.dateFormat
  104.             cell.textLabel?.text = data.placeholder
  105.             cell.detailTextLabel?.text = dateFormatter.string(from: data.date)
  106.             cell.imageView?.image = data.image
  107.             cell.accessoryType = .disclosureIndicator
  108.  
  109.             cell.selectionStyle = .none
  110.             return cell
  111.         case .disclosure(let image, let placeholder, let text, _):
  112.             let cell = tableView.dequeueReusableCell(withIdentifier: RightValueTableViewCell.defaultCellReuseIdentifier, for: indexPath)
  113.  
  114.             cell.textLabel?.text = placeholder
  115.             cell.detailTextLabel?.text = text
  116.             cell.imageView?.image = image
  117.             cell.accessoryType = .disclosureIndicator
  118.  
  119.             cell.selectionStyle = .none
  120.             return cell
  121.         }
  122.     }
  123.  
  124.     func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
  125.         return cells[section].title
  126.     }
  127. }
  128.  
  129. extension FormManager: UITableViewDelegate {
  130.     func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
  131.  
  132.         if let lastTextfieldCell = lastSelectedInlineTextfieldCell {
  133.             lastTextfieldCell.resignTextFieldResponder()
  134.         }
  135.  
  136.         let cellData = cellTypeFor(indexPath: indexPath)
  137.  
  138.         tableView.beginUpdates()
  139.         switch cellData {
  140.         case .textField:
  141.             lastSelectedInlineTextfieldCell = tableView.cellForRow(at: indexPath) as? InlineTextFieldTableViewCell
  142.             _ = lastSelectedInlineTextfieldCell?.becomeFirstResponder()
  143.             hideDatePicker(for: tableView)
  144.         case .datePicker:
  145.             lastSelectedInlineTextfieldCell = nil
  146.             if let datePickerIndexPath = currentlyShownDatePickerIndexPath {
  147.                 if  datePickerIndexPath.row - 1 == indexPath.row, datePickerIndexPath.section == indexPath.section { //hit the same row
  148.                     hideDatePicker(for: tableView)
  149.                 } else { // hit different row with datePicker
  150.                     tableView.deleteRows(at: [datePickerIndexPath], with: .fade)
  151.                     attachDatePickerCell(to: tableView, under: indexPath)
  152.                 }
  153.             } else {
  154.                 hideDatePicker(for: tableView)
  155.                 attachDatePickerCell(to: tableView, under: indexPath)
  156.             }
  157.         case .disclosure(_, _, _, let action):
  158.             lastSelectedInlineTextfieldCell = nil
  159.             hideDatePicker(for: tableView)
  160.             action()
  161.         }
  162.         tableView.endUpdates()
  163.     }
  164.  
  165.     private func attachDatePickerCell(to tableView: UITableView, under indexPath: IndexPath) {
  166.         let newDatePickerIndexPath = indexPathToInsertDatePicker(indexPath: indexPath)
  167.         self.currentlyShownDatePickerIndexPath = newDatePickerIndexPath
  168.         tableView.insertRows(at: [newDatePickerIndexPath], with: .fade)
  169.         tableView.deselectRow(at: indexPath, animated: true)
  170.     }
  171.  
  172.     private func hideDatePicker(for tableView: UITableView) {
  173.         if let datePickerIndexPath = currentlyShownDatePickerIndexPath {
  174.             tableView.deleteRows(at: [datePickerIndexPath], with: .fade)
  175.         }
  176.         self.currentlyShownDatePickerIndexPath = nil
  177.     }
  178. }
  179.  
  180. extension FormManager: InlineDatePickerDelegate {
  181.     func didChangeDate(date: Date, indexPath: IndexPath) {
  182.         let cellData = cellTypeFor(indexPath: indexPath)
  183.  
  184.         if case FormCellType.datePicker(let data) = cellData,
  185.            let cell = delegate?.tableView.cellForRow(at: indexPath) {
  186.             dateFormatter.dateFormat = data.dateFormat
  187.             data.didChangeValue(date.timeIntervalSince1970)
  188.             cell.detailTextLabel?.text = dateFormatter.string(from: date)
  189.         }
  190.     }
  191. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top