Swiftpack.co - Package - bcylin/QuickTableViewController

QuickTableViewController

GitHub Actions Codecov Carthage compatible CocoaPods Compatible Platform Swift 5

A simple way to create a table view for settings, including:

  • Table view cells with UISwitch
  • Table view cells with center aligned text for tap actions
  • A section that provides mutually exclusive options
  • Actions performed when the row reacts to the user interaction
  • Easy to specify table view cell image, cell style and accessory type

Usage

Set up tableContents in viewDidLoad:

import QuickTableViewController

final class ViewController: QuickTableViewController {

  override func viewDidLoad() {
    super.viewDidLoad()

    tableContents = [
      Section(title: "Switch", rows: [
        SwitchRow(text: "Setting 1", switchValue: true, action: { _ in }),
        SwitchRow(text: "Setting 2", switchValue: false, action: { _ in })
      ]),

      Section(title: "Tap Action", rows: [
        TapActionRow(text: "Tap action", action: { [weak self] in self?.showAlert($0) })
      ]),

      Section(title: "Navigation", rows: [
        NavigationRow(text: "CellStyle.default", detailText: .none, icon: .named("gear")),
        NavigationRow(text: "CellStyle", detailText: .subtitle(".subtitle"), icon: .named("globe")),
        NavigationRow(text: "CellStyle", detailText: .value1(".value1"), icon: .named("time"), action: { _ in }),
        NavigationRow(text: "CellStyle", detailText: .value2(".value2"))
      ], footer: "UITableViewCellStyle.Value2 hides the image view."),

      RadioSection(title: "Radio Buttons", options: [
        OptionRow(text: "Option 1", isSelected: true, action: didToggleSelection()),
        OptionRow(text: "Option 2", isSelected: false, action: didToggleSelection()),
        OptionRow(text: "Option 3", isSelected: false, action: didToggleSelection())
      ], footer: "See RadioSection for more details.")
    ]
  }

  // MARK: - Actions

  private func showAlert(_ sender: Row) {
    // ...
  }

  private func didToggleSelection() -> (Row) -> Void {
    return { [weak self] row in
      // ...
    }
  }

}

NavigationRow

Detail Text Styles

NavigationRow(text: "UITableViewCellStyle.default", detailText: .none)
NavigationRow(text: "UITableViewCellStyle", detailText: .subtitle(".subtitle")
NavigationRow(text: "UITableViewCellStyle", detailText: .value1(".value1")
NavigationRow(text: "UITableViewCellStyle", detailText: .value2(".value2"))

Subtitle and the initializers with title/subtitle are deprecated and will be removed in v2.0.0.

Accessory Type

  • The NavigationRow shows with different accessory types based on the action and accessoryButtonAction closures:
var accessoryType: UITableViewCell.AccessoryType {
  switch (action, accessoryButtonAction) {
  case (nil, nil):      return .none
  case (.some, nil):    return .disclosureIndicator
  case (nil, .some):    return .detailButton
  case (.some, .some):  return .detailDisclosureButton
  }
}
  • The action will be invoked when the table view cell is selected.
  • The accessoryButtonAction will be invoked when the accessory button is selected.

Images

enum Icon {
  case named(String)
  case image(UIImage)
  case images(normal: UIImage, highlighted: UIImage)
}
  • Images in table view cells can be set by specifying the icon of each row.
  • Table view cells in UITableViewCellStyle.value2 will not show the image view.

SwitchRow

  • A SwitchRow is representing a table view cell with a UISwitch as its accessoryView.
  • The action will be invoked when the switch value changes.

TapActionRow

  • A TapActionRow is representing a button-like table view cell.
  • The action will be invoked when the table view cell is selected.
  • The icon, detail text, and accessory type are disabled in TapActionRow.

OptionRow

  • An OptionRow is representing a table view cell with .checkmark.
  • The action will be invoked when the selected state is toggled.
let didToggleSelection: (Row) -> Void = { [weak self] in
  if let option = $0 as? OptionRowCompatible, option.isSelected {
    // to exclude the event where the option is toggled off
  }
}

RadioSection

  • RadioSection allows only one selected option at a time.
  • Setting alwaysSelectsOneOption to true will keep one of the options selected.
  • OptionRow can also be used with Section for multiple selections.

Customization

Rows

All rows must conform to Row and RowStyle. Additional interface to work with specific types of rows are represented as different protocols:

  • NavigationRowCompatible
  • OptionRowCompatible
  • SwitchRowCompatible
  • TapActionRowCompatible

Cell Classes

A customized table view cell type can be specified to rows during initialization.

// Default is UITableViewCell.
NavigationRow<CustomCell>(text: "Navigation", detailText: .none)

// Default is SwitchCell.
SwitchRow<CustomSwitchCell>(text: "Switch", switchValue: true, action: { _ in })

// Default is TapActionCell.
TapActionRow<CustomTapActionCell>(text: "Tap", action: { _ in })

// Default is UITableViewCell.
OptionRow<CustomOptionCell>(text: "Option", isSelected: true, action: { _ in })

Since the rows carry different cell types, they can be matched using either the concrete types or the related protocol:

let action: (Row) -> Void = {
  switch $0 {
  case let option as OptionRow<CustomOptionCell>:
    // only matches the option rows with a specific cell type
  case let option as OptionRowCompatible:
    // matches all option rows
  default:
    break
  }
}

Overwrite Default Configuration

You can use register(_:forCellReuseIdentifier:) to specify custom cell types for the table view to use. See CustomizationViewController for the cell reuse identifiers of different rows.

Table view cell classes that conform to Configurable can take the customization during tableView(_:cellForRowAt:):

protocol Configurable {
  func configure(with row: Row & RowStyle)
}

Additional setups can also be added to each row using the customize closure:

protocol RowStyle {
  var customize: ((UITableViewCell, Row & RowStyle) -> Void)? { get }
}

The customize closure overwrites the Configurable setup.

UIAppearance

As discussed in issue #12, UIAppearance customization works when the cell is dequeued from the storyboard. One way to work around this is to register nib objects to the table view. Check out AppearanceViewController for the setup.

tvOS Differences

  • UISwitch is replaced by a checkmark in SwitchCell.
  • TapActionCell does not use center aligned text.
  • NavigationRow.accessoryButtonAction is not available.
  • Cell image view's left margin is 0.

Limitation

When to use QuickTableViewController?

QuickTableViewController is good for presenting static table contents, where the sections and rows don't change dynamically after viewDidLoad.

It's possible to update the table contents by replacing a specific section or row. Using different styles on each row requires additional configuration as described in the Customization section.

When not to use it?

QuickTableViewController is not designed for inserting and deleting rows. It doesn't handle table view reload animation either. If your table view needs to update dynamically, you might want to consider other solutions such as IGListKit.

Documentation

Requirements

Pre 1.0 versions

QuickTableViewController | iOS | tvOS | Xcode | Swift ------------------------ | :--: | :--: | :---: | :---: ~> 0.1.0 | 8.0+ | - | 6.4 | 1.2 ~> 0.2.0 | 8.0+ | - | 7.0 | 2.0 ~> 0.3.0 | 8.0+ | - | 7.3 | 2.2 ~> 0.4.0 | 8.0+ | - | 8.0 | 2.3 ~> 0.5.0 | 8.0+ | - | 8.0 | 3.0 ~> 0.6.0 | 8.0+ | - | 8.3 | 3.1 ~> 0.7.0 | 8.0+ | - | 9.0 | 3.2 ~> 0.8.0 | 8.0+ | - | 9.1 | 4.0 ~> 0.9.0 | 8.0+ | - | 9.3 | 4.1


QuickTableViewController | iOS | tvOS | Xcode | Swift ------------------------ | :--: | :--: | :---: | :---: ~> 1.0.0 | 8.0+ | 9.0+ | 9.4 | 4.1 ~> 1.1.0 | 8.0+ | 9.0+ | 10.1 | 4.2 ~> 1.2.0 | 8.0+ | 9.0+ | 10.2 | 5.0 ~> 1.3.0 | 9.0+ | 9.0+ | 11.7 | 5.2

Installation

Use Swift Package Manager

Follow the instructions at Adding Package Dependencies to Your App and use version v1.2.1 or later. (requires Xcode 11)

Use CocoaPods

Create a Podfile with the following specification and run pod install.

platform :ios, '9.0'
use_frameworks!

pod 'QuickTableViewController'

Use Carthage

Create a Cartfile with the following specification and run carthage update QuickTableViewController. Follow the instructions to add the framework to your project.

github "bcylin/QuickTableViewController"

Xcode 12 workaround Guide: https://github.com/Carthage/Carthage/blob/master/Documentation/Xcode12Workaround.mdx

Use Git Submodule

git submodule add -b master git@github.com:bcylin/QuickTableViewController.git Dependencies/QuickTableViewController
  • Drag QuickTableViewController.xcodeproj to your app project as a subproject.
  • On your application target's Build Phases settings tab, add QuickTableViewController-iOS to Target Dependencies.

License

QuickTableViewController is released under the MIT license. See LICENSE for more details. Image source: iconmonstr.

Github

link
Stars: 370

Dependencies

Used By

Total: 0

Releases

v.1.3.0 - 2020-10-05 23:19:41

  • Use SF Symbols as icon images, #41 by @ezfe
  • Make init(style:) a designated initializer
  • Add an option to override table view for style configuration, #74 by @Tobisaninfo
  • Set IPHONEOS_DEPLOYMENT_TARGET to 9.0

v1.2.4 - 2020-07-02 22:13:45

  • Fix an issue where the same identifier is used for different cell types #50

v1.2.3 - 2020-06-23 21:23:00

  • Fix Swift version in podspec

v.1.2.2 - 2020-06-07 17:46:38

Fixes

Project Updates

  • Add an example of dynamic table, #42 by @twodayslate
  • Convert specs to XCTests
  • Move tests to GitHub Actions

v1.2.1 - 2019-12-02 19:50:28

  • Support Swift Package

v1.2.0 - 2019-06-14 22:10:07

v1.1.1 - 2019-05-06 16:37:42

  • Fix the animated OptionRow deselection
  • Invoke accessoryButtonAction asynchronously to match the behaviour of row action
  • Remove ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES from build settings

v1.1.0 - 2019-01-06 14:57:31

Enhancements

  • Swift 4.2, #20 by @getaaron and #28 by @mttcrsp
  • tvOS UI tests, #27 by @FraDeliro
  • Subtitle is deprecated and will be removed in v2.0.0
  • Rename Row's title and subtitle to text and detail text to align with UITableViewCell's naming
  • Enable detailText in OptionRow and SwitchRow
  • Add accessoryButtonAction to NavigationRow

v1.0.0 - 2018-09-19 19:35:25

Enhancements

  • Support tvOS

v0.9.1 - 2018-04-17 15:53:12

Fixes

  • Fix the property setter in RadioSection and change Row to a class protocol, #14 by @z3bi

v0.9.0 - 2018-04-05 08:55:54

Breaking

  • Change the Icon type (since v0.2.0) from struct to enum:

    enum Icon {
      case named(String)
      case image(UIImage)
      case images(normal: UIImage, highlighted: UIImage)
    }
    
  • Rename the protocols (introduced in v0.8.1) that define specific rows regardless of their associated cell types:

    • NavigationRowCompatible
    • OptionSelectableOptionRowCompatible
    • SwitchableSwitchRowCompatible
    • TappableTapActionRowCompatible

v0.8.4 - 2018-03-21 05:04:12

Fixes

  • Use TapActionCell's tintColor as its label textColor, #13 by @sanekgusev

v0.8.3 - 2018-02-17 05:16:10

Fixes

  • Avoid some unwanted animation when the row action also involves table view reload

v0.8.2 - 2018-01-01 16:42:09

Fixes

  • Fix the SwitchCell configuration with custom row classes

v0.8.1 - 2017-12-11 17:27:28

Fixes

  • Unhighlight the selected row in the radio section when it's tapped with alwaysSelectsOneOption set to true
  • Fix the empty image name that causes CUICatalog: Invalid asset name supplied: ''
  • Allow OptionRow to be used with custom table view cells
  • Fix the actions that are not invoked in rows with custom table view cells

v0.8.0 - 2017-12-02 02:26:06

Enhancements

  • Swift 4

v0.7.1 - 2017-10-19 14:41:35

Enhancements

  • Allow predefined NavigationRow, SwitchRow, TapActionRow, and OptionRow to be subclassable

v0.6.2 - 2017-08-18 07:26:14

Enhancements

  • Mark properties and methods open in the open classes
  • Improve the documentation

v0.7.0 - 2017-08-23 03:47:17

Breaking

  • Remove the accessory view from the AccessoryEnabled protocol
  • Merge IconEnabled and AccessoryEnabled properties into the RowStyle protocol

Enhancements

  • Add OptionRow and RadioSection to support mutually exclusive options

Fixes

  • Use both cell type and cell style as the reuse identifiers for navigation rows to distinguish customized cell classes

v0.6.1 - 2017-08-16 02:13:04

Enhancements

  • UI testing
  • Change sections and rows from structs to classes
  • Allow customized cell classes to implement the Configurable method in addition to the default setup

Fixes

  • UISwitch animation #9

v0.6.0 - 2017-08-08 12:23:34

Breaking

  • Deprecate the customization using table view register(_:forCellReuseIdentifier:)
  • Move the tableView configuration from loadView() to viewDidLoad()

Enhancements

  • Specify table view cell types to rows during initialization
  • Separate RowStyle from the original Row protocol
  • Add an additional cell customization ((UITableViewCell, Row & RowStyle) -> Void)? for each row

Project Updates

  • CocoaPods 1.3.0

v0.5.3 - 2017-04-24 19:58:25

Fixes

  • Fix the cell reuse identifier of SwitchRow and TapActionRow to be compatible with 0.5.x
  • https://github.com/bcylin/QuickTableViewController/blob/develop/CHANGELOG.md#v053

v0.5.2 - 2017-04-14 10:32:02

Enhancements

  • Xcode 8.3
  • Make the image name and highlighted image name of Icon public readonly

v0.5.1 - 2016-10-08 08:06:42

Enhancements

  • Specify table view cell reuse identifier for each type of row
  • Update Swift syntax

v0.5.0 - 2016-10-05 14:23:56

Breaking

  • Swift 3

Project Updates

  • Auto generated docs
  • Move the example to the project root directory

v0.4.0 - 2016-09-20 13:41:52

Enhancements

  • Swift 2.3
  • Improved documentation
  • Make the images of Icon readonly

Project Updates

  • CocoaPods 1.1.0.rc.2
  • Run tests with fastlane scan
  • Integrate with danger.systems

v0.3.0 - 2016-06-10 16:45:36

Enhancements

  • Swift 2.2
  • SwitchRow now conforms to IconEnabled (#2, #4). Thanks to @drinkius.

Project Updates

  • CocoaPods 1.0.1
  • Calculate code coverage
  • SwiftLint with Hound CI

v0.2.0 - 2016-01-06 17:12:31

Breaking

  • Swift 2

Enhancements

  • Row and Subtitle now conform to Equatable
  • Specify table view cell images with Icon, which includes highlighted image
  • Separate self.view from self.tableView in QuickTableViewController

Fixes

  • Fix the access control on the overridden initializer

Project Updates

  • Run tests on Travis CI
  • Clean up syntax with SwiftLint

v0.1.1 - 2015-10-19 14:40:30

Fixes

  • Change the deployment target from iOS 8.4 to 8.0

v0.1.0 - 2015-09-08 16:18:42

  • Initial release written in Swift 1.2
  • Basic layout:
    • Section
    • NavigationRow with Subtitle
    • SwitchRow
    • TapActionRow