Latest 1.1
Homepage https://github.com/jrsaruo/SwiftyTable
License MIT
Platforms ios 10.0, requires ARC
Authors

iOS 10.0+
Swift 4.2
Cocoapods Compatible
Carthage compatible

Pure-Swift library for statically typed table components.

Requirements

  • Xcode 10+
  • Swift 4.2+
  • iOS 10.0+

Installation

CocoaPods

CocoaPods is a dependency manager for Cocoa projects.

To integrate SwiftyTable into your Xcode project using CocoaPods, add the following line to your Podfile and run pod install.

pod 'SwiftyTable', git: 'https://github.com/jrsaruo/SwiftyTable.git'

Carthage

Carthage is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks.

To integrate SwiftyTable into your Xcode project using Carthage, specify it in your Cartfile:

github "jrsaruo/SwiftyTable"

Run carthage update to build the framework and drag the built SwiftyTable.framework into your Xcode project.

Features

1. Reusable

No need to define reuse identifiers for UITableViewCell, UITableHeaderFooterView, UICollectionViewCell and UICollectionReusableView.

class CustomCell: UITableViewCell {
    var customProperty: String?
}

let tableView = UITableView()
tableView.register(CustomCell.self) // NO NEED to define reuse identifier!

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(of: CustomCell.self, for: indexPath)
    cell.customProperty = "NO NEED to use 'as! CustomCell'"
    return cell
}

2. Statically typed table components

Following implementation is hard to read and will easily cause bugs.

switch indexPath.section {
case 0:
    switch indexPath.row {
    case 0:
        cell.textLabel?.text = "Username"
    case 1:
        cell.textLabel?.text = "Email"
    case 2:
        cell.textLabel?.text = "phoneNumber"
    default:
        break
    }
case 1:
    cell.accessoryType = .disclosureIndicator
default:
    break
}

↓ If you use SwiftyTable, the code becomes much better!

switch Section(indexPath.section) {
case .profile:
    cell.textLabel?.text = ProfileRow(indexPath.row).title
case .information:
    cell.accessoryType = .disclosureIndicator
}

Easy to define table sections or rows

enum Section: Int, TableSection, CaseIterable {
    case profile
    case information
}

enum ProfileRow: Int, TableRow, CaseIterable {
    case username
    case email
    case phoneNumber

    var title: String { ... }
}

enum InformationRow: Int, TableRow, CaseIterable {
    case help
    case aboutApp
}

Readable and Flexible

extension ViewController: UITableViewDataSource {

    func numberOfSections(in tableView: UITableView) -> Int {
        return Section.count // automatically returns 2.
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        switch Section(section) {
        case .profile:
            return ProfileRow.count // automatically returns 3.
        case .information:
            return InformationRow.count // automatically returns 2.
        }
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(of: UITableViewCell.self, for: indexPath)

        switch Section(indexPath.section) { // default case is unnecessary.
        case .profile:
            cell.textLabel?.text = ProfileRow(indexPath.row).title
        case .information:
            cell.accessoryType = .disclosureIndicator
        }

        return cell
    }

}

You can easily change sections or rows like this. Even if the change causes some problems, the compiler will tell you about it.

enum InformationRow: Int, TableRow, CaseIterable {
    case contact // just add cases to increase rows
    case aboutApp // just swap cases to change the order of rows
    case help
}

Usage

Please create Section/Row enumeration that has integer raw values and conforms to TableSection/TableRow and CaseIterable.
Raw values must correspond to its section/row numbers.

enum SomeSection: Int, TableSection, CaseIterable {
    case zero
    case one
    case two
}

SomeSection.count // automatically returns 3.
SomeSection(0) // .zero
SomeSection(1) // .one
SomeSection(2) // .two
SomeSection(3) // assertionFailure

enum SomeRow: Int, TableRow, CaseIterable {
    case zero, one, two, three
}

If the type does not conform to CaseIterable, you need to implement count property. However, hard coding like this can causes bugs, so you should use CaseIterable.

enum SomeSection: Int, TableSection {
    case zero
    case one
    case two
    static var count: Int { return 3 }
}

Initialize Section or Row with specified section/row number.

let section = SomeSection(indexPath.section)
let row = SomeRow(indexPath.row)

Initialize IndexPath with specified Section/Row.

// these indexPaths are the same.
let indexPath1 = IndexPath(row: 1, section: 0)
let indexPath2 = IndexPath(row: SomeRow.one, section: 0)
let indexPath3 = IndexPath(row: 1, section: SomeSection.zero)
let indexPath4 = IndexPath(row: SomeRow.one, section: SomeSection.zero)

License

SwiftyTable is under MIT license. See the LICENSE file for more info.

Latest podspec

{
    "name": "SwiftyTable",
    "version": "1.1",
    "license": {
        "type": "MIT",
        "file": "LICENSE"
    },
    "summary": "Pure-Swift library for statically typed table components.",
    "homepage": "https://github.com/jrsaruo/SwiftyTable",
    "authors": {
        "Yusaku Nishi": "[email protected]"
    },
    "social_media_url": "http://twitter.com/jrsaruo",
    "platforms": {
        "ios": "10.0"
    },
    "source": {
        "git": "https://github.com/jrsaruo/SwiftyTable.git",
        "tag": "v1.1"
    },
    "source_files": "SwiftyTable/**/*.swift",
    "requires_arc": true
}

Pin It on Pinterest

Share This