Skip to content

Latest commit

 

History

History
195 lines (154 loc) · 5.11 KB

UITableCellsAndTypes.md

File metadata and controls

195 lines (154 loc) · 5.11 KB

UITableView Cells and Types

You can do some real cool things with Section Row and enum by defining a cell.

And then defining various row types and simply switching on them to configure the cell.

ViewController

import UIKit

// MARK: - TableSection
extension ViewController {
    struct TableSection {
        let title: String
        let rows: [RowType]

        enum RowType {
            case depositTo(DepositModel)
            case requestTo(RecipientModel)
            case sentDate(Date)
            case transactionFee

            var fieldLabel: String {
                switch self {
                case .depositTo: return "Deposit to"
                case .requestTo: return "Request to"
                case .sentDate: return "Date sent"
                case .transactionFee: return "Transaction fee"
                }
            }
        }
    }
}

class ViewController: UIViewController {

    var tableView = UITableView()

    var sections: [TableSection] = []

    var eTransferDetails: RequestDetailModel? {
        didSet {
            populateTable()
            tableView.reloadData()
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        setup()
    }

    private func setup() {
        tableView.dataSource = self
        tableView.rowHeight = 128
        tableView.register(Cell.self)

        view = tableView

        fetchETransferDetails()
    }

    private func populateTable() {
        guard let details = self.eTransferDetails else { return }
        var rows: [TableSection.RowType] = []

        switch details.eTransferStatus {
        case .available:
            rows.append(.depositTo(details.depositAccount))
            rows.append(.requestTo(details.requestedFrom))
            rows.append(.sentDate(details.executionDate))
            rows.append(.transactionFee)
        case .cancelled:
            rows.append(.depositTo(details.depositAccount))
            rows.append(.requestTo(details.requestedFrom))
            rows.append(.sentDate(details.executionDate))
            rows.append(.transactionFee)
        }

        // Currently only one section, so always handle after switch
        self.sections = [TableSection(title: "", rows: rows)]
    }
}

// MARK: - UITableViewDataSource
extension ViewController: UITableViewDataSource {
    func numberOfSections(in tableView: UITableView) -> Int {
        return sections.count
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return sections[section].rows.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell: Cell = tableView.dequeueResuableCell(for: indexPath)
        let rowType = sections[indexPath.section].rows[indexPath.row]
        cell.configure(rowType: rowType)
        return cell
    }
}

// MARK: - Networking
extension ViewController {
    private func fetchETransferDetails() {
        let depositAccountModel = DepositModel(accountName: "Savings", accountNumber: "0779")
        let recipientModel = RecipientModel(alias: "Jonathan", email: "[email protected]")
        let details = RequestDetailModel(eTransferStatus: .cancelled, depositAccount: depositAccountModel, requestedFrom: recipientModel, executionDate: Date())
        eTransferDetails = details
    }
}

Cell

import UIKit

final class Cell: UITableViewCell {

    @IBOutlet weak var fieldLabel: UILabel!
    @IBOutlet weak var primaryLabel: UILabel!
    @IBOutlet weak var secondaryLabel: UILabel!
    @IBOutlet weak var accountNumberLabel: UILabel!

    override func awakeFromNib() {
        super.awakeFromNib()
        selectionStyle = .none
        accountNumberLabel.isHidden = true
        secondaryLabel.isHidden = true
        [fieldLabel,
        primaryLabel,
        secondaryLabel,
         accountNumberLabel].forEach { $0?.textColor = .gray }
    }
}

extension Cell {
    typealias RowType = ViewController.TableSection.RowType
    func configure(rowType: RowType) {
        fieldLabel.text = rowType.fieldLabel

        switch rowType {
        case .sentDate(let date):
            primaryLabel.text = date.fullMonthDayYearString

        case .requestTo(let recipient):
            primaryLabel.text = recipient.alias
            secondaryLabel.text = recipient.email
            secondaryLabel.isHidden = false

        case .depositTo(let account):
            primaryLabel.text = account.accountName
            accountNumberLabel.text = "(\(account.accountNumber))"
            accountNumberLabel.isHidden = false

        case .transactionFee:
            primaryLabel.text = "$1.50"
        }
    }
}

ViewModel

enum TransferStatus: String, Codable {
    case available = "Available"
    case cancelled = "Cancelled"
}

struct DepositModel {
    var accountName: String
    var accountNumber: String
}

struct RecipientModel {
    let alias: String
    let email: String
}

struct RequestDetailModel {
    var eTransferStatus: TransferStatus
    var depositAccount: DepositModel
    var requestedFrom: RecipientModel
    var executionDate: Date
}