Simple static table views for iOS in Swift.

Related tags

Table View Static
Overview

Static Logo

Version Status Swift Version Carthage compatible

Simple static table views for iOS in Swift. Static's goal is to separate model data from presentation. Rows and Sections are your “view models” for your cells. You simply specify a cell class to use and that handles all of the presentation. See the usage section below for details.

Version Compatibility

Swift Version Static Version
5.0+ 4.0.2
4.2+ 3.0.1
3.2+ 2.1
3.0.1 2.0.1
3.0 2.0
2.3 1.2
2.2 1.1
2.0 - 2.1 1.0

Installation

Carthage

Carthage is the recommended way to install Static. Add the following to your Cartfile:

github "venmo/Static"

CocoaPods

CocoaPods is a dependency manager for Cocoa projects. To install Static with CocoaPods:

Make sure CocoaPods is installed (Static requires version 0.37 or greater).

Update your Podfile to include the following:

use_frameworks!
pod 'Static', git: 'https://github.com/venmo/Static'

Run pod install.

Manual

For manual installation, it's recommended to add the project as a subproject to your project or workspace and adding the appropriate framework as a target dependency.

Usage

An example app is included demonstrating Static's functionality.

Getting Started

To use Static, you need to define Rows and Sections to describe your data. Here's a simple example:

import Static

Section(rows: [
    Row(text: "Hello")
])

You can configure Sections and Rows for anything you want. Here's another example:

Section(header: "Money", rows: [
    Row(text: "Balance", detailText: "$12.00", accessory: .disclosureIndicator, selection: {
        // Show statement
    }),
    Row(text: "Transfer to Bank…", cellClass: ButtonCell.self, selection: {
        [unowned self] in
        let viewController = ViewController()
        self.presentViewController(viewController, animated: true, completion: nil)
    })
], footer: "Transfers usually arrive within 1-3 business days.")

Since this is Swift, we can provide instance methods instead of inline blocks for selections. This makes things really nice. You don't have to switch on index paths in a tableView:didSelectRowAtIndexPath: any more!

Customizing Appearance

The Row never has access to the cell. This is by design. The Row shouldn't care about its appearance other than specifying what will handle it. In practice, this has been really nice. Our cells have one responsibility.

There are several custom cells provided:

  • Value1Cell — This is the default cell. It's a plain UITableViewCell with the .Value1 style.
  • Value2Cell — Plain UITableViewCell with the .Value2 style.
  • SubtitleCell — Plain UITableViewCell with the .Subtitle style.
  • ButtonCell — Plain UITableViewCell with the .Default style. The textLabel's textColor is set to the cell's tintColor.

All of these conform to Cell. The gist of the protocol is one method:

func configure(row row: Row)

This gets called by DataSource (which we'll look at more in a minute) to set the row on the cell. There is a default implementation provided by the protocol that simply sets the Row's text on the cell's textLabel, etc. If you need to do custom things, this is a great place to hook in.

Row also has a context property. You can put whatever you want in here that the cell needs to know. You should try to use this as sparingly as possible.

Custom Row Accessories

Row has an accessory property that is an Accessory enum. This has cases for all of UITableViewCellAccessoryType. Here's a row with a checkmark:

Row(text: "Buy milk", accessory: .checkmark)

Easy enough. Some of the system accessory types are selectable (like that little i button with a circle around it). You can make those and handle the selection like this:

Row(text: "Sam Soffes", accessory: .detailButton({
  // Show info about this contact
}))

Again, you could use whatever function here. Instance methods are great for this.

There is an additional case called .view that takes a custom view. Here's a Row with a custom accessory view:

Row(text: "My Profile", accessory: .view(someEditButton))

Custom Section Header & Footer Views

Section has properties for header and footer. These take a Section.Extremity. This is an enum with Title and View cases. Extremity is StringLiteralConvertible you can simply specify strings if you want titles like we did the Getting Started section.

For a custom view, you can simply specify the View case:

Section(header: .view(yourView))

The height returned to the table view will be the view's bounds.height so be sure it's already sized properly.

Working with the Data Source

To hook up your Sections and Rows to a table view, simply initialize a DataSource:

let dataSource = DataSource()
dataSource.sections = [
    Section(rows: [
        Row(text: "Hello")
    ])
]

Now assign your table view:

dataSource.tableView = tableView

Easy as that! If you modify your data source later, it will automatically update the table view for you. It is important that you don't change the table view's dataSource or delegate. The DataSource needs to be those so it can handle events correctly. The purpose of Static is to abstract all of that away from you.

Wrapping Up

There is a provided TableViewController that sets up a DataSource for you. Here's a short example:

class SomeViewController: TableViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        dataSource.sections = [
            Section(rows: [
                Row(text: "Hi")
            ]),
            // ...
        ]
    }
}

Enjoy.

Comments
  • Blank section headers are displayed under iOS 11

    Blank section headers are displayed under iOS 11

    It looks like blank section headers/footers are being shown on devices running iOS 11 (as of beta 2) when a Section is initialized with nil as a header/footer extremity.

    The below screenshots were taken with the example project after changing the value of the header parameter of the first section to nil.

    | iOS 10 | iOS 11 | | ------ | ------ | | screen shot 2017-06-29 at 4 10 41 pm | screen shot 2017-06-29 at 4 10 39 pm |

    opened by nealyoung 11
  • Add ability to receive UITableViewDelegate & UIScrollViewDelegate messages from UITableView

    Add ability to receive UITableViewDelegate & UIScrollViewDelegate messages from UITableView

    Using Static for your table view solutions previously caused some limitations for certain use cases. Since the DataSource object is both the dataSource & delegate of the UITableView instance, users of the Static library were unable to receive the UITableViewDelegate methods they might need to do things like reacting to scrolling, header displays or any further actions.

    This change introduces a new weak property on DataSource: tableViewDelegate. This needs to be set during init, due to the execution timing of forwardingTarget & respondsToSelector. Using those two methods, the unimplemented UITableViewDelegate methods can get forwarded to the delegate that the user specifies, unlocking this missing functionality, mentioned in #97, #78, #72.

    Two already implemented UITableViewDelegate functions will also forward the message to the tableViewDelegate property (if it implements those methods). The other remaining function's behavior is already fully exposed by Static, so it didn't need to be changed.

    Other notes about this change/PR:

    • This is backwards compatible. Updated version based on semantic versioning.
    • Unit test added, fully covers new code.
    • Example ViewController class modified to include example of this functionality.
    opened by jaredegan 8
  • Remove reference to functions as selections

    Remove reference to functions as selections

    This was causing memory leaks as the closure referenced self, without declaring it's ownership of self. From the Swift docs: "A strong reference cycle can also occur if you assign a closure to a property of a class instance, and the body of that closure captures the instance...[this] strong reference cycle occurs because closures, like classes, are reference types"

    By adding the [unowned self] to each selection, we remove any retain cycles.

    opened by eliperkins 8
  • Simpler TableViewController

    Simpler TableViewController

    Converted to use plain UITableViewController instead of rolling our own. I totally get the value of using a plain UIViewController with its table view as a subview of view, but that's not a decision Static should be making for its consumers in my opinion. I think the system default should be Static's default, and if you want something custom, you're welcome to customize it.

    opened by soffes 6
  • Make Row be agnostic of its presentation

    Make Row be agnostic of its presentation

    Row shouldn't know anything about how its displayed (with the exception of specifying a class to display it). This was the original design of Static. I'm proposing going back to that mindset with a few small changes.

    Remove Height

    If you want a custom height for a cell, set tableView.estimatedRowHeight and then add a constraint to cell.contentView to set its height. This is a much more flexible way to go about custom heights if you need varying heights in the same table view.

    Remove Image Tint Color

    From the very beginning, you couldn't set a label's color. This was by design. If you wanted to change the presentation of a label, you had to make a custom cell. I think this same thinking applies to images. If you want to set the color of an image, either do it before it gets to the Row or do it in the cell. Having the Row tell the cell what color it is violates its lack of understanding of presentation.


    I tried to explain my reasoning. Hopefully this doesn't seem silly. It's awesome to see people contributing to Static, but I think these two additions are going the wrong direction. Thoughts? :heart:

    opened by soffes 6
  • Upgrade to Swift 3 compatibility

    Upgrade to Swift 3 compatibility

    Took a stab at running the Xcode Swift 3 migration for #83 ; everything seemed to carry over quite well. Test suite passes, and everything looks good in the sample project as well.

    opened by chrismanderson 5
  • More documentation

    More documentation

    The note about UIKit support is the main thing here. Originally, I was going to dispatch_async to the main queue for everything that touches UIKit, but that got complicated quick. I think it makes things harder to work with since everything is async. I'd rather consumers treat DataSource like any other UIKit class and only access it from the main queue.

    Thoughts? @ayanonagon @hyperspacemark

    opened by soffes 5
  • Bugfix: SectionFooterView AutoDimension Support

    Bugfix: SectionFooterView AutoDimension Support

    Problem:

    1. I noticed our app was manually laying out subviews in our sectionFooters when I didn't see the need to. (Given auto-layout/intrinsic size support)

    eg.. (Unnecessarily maintaining and calculation including insets/frame)

        override func layoutSubviews() {
            super.layoutSubviews()
            var frame = self.frame
            frame.size = CGSize(width: frame.size.width, height: signUpInstructionsLabel.systemLayoutSizeFitting(UILayoutFittingCompressedSize).height + textInsets.top + textInsets.bottom)
            self.frame = frame
        }
    
    1. After recent changes, Group tableView's which had nil section extremity defaulted to zero, which drops the standard spacing between sections. (Using current master)
    screen shot 2017-08-28 at 9 39 07 pm

    Notable info: Statics currently has deploy target of iOS8, which did not yet support automatic sectionFooterView dimensioning.

    Solution:

    • Offer autosizing option which uses UITableViewAutomaticDimension rather than view's original bounds height. Retain original .view(_) case in the event some clients were already sizing beforehand limiting integration breaks.
    • Bump deploy target to iOS9 for clean integration.
    • Revert 2 previous PRs focused on same issue

    Testing: Tested with simulators

    • [x] iOS11 beta5 on iPhone 7 (Friendly)
    • [x] iOS 10.3 on iPhone 6. (Requires owner to set estimatedSectionHeader/FooterHeights to > 0

    Did not test on iOS 9

    opened by dmiluski 4
  • add possibility to react on will display header and footer

    add possibility to react on will display header and footer

    As reported in #78 I decided to make small PR with possibility to quickly access two methods of UITableViewDelegate:

    • tableView(_:, willDisplayHeaderView:, forSection:)
    • tableView(_:, willDisplayFooterView:, forSection:)

    The reason we need to have the simplest possibility to access those method is that UIKit somehow overrides header view appearance (for UITableViewHeaderFooterVIew) and those two methods can be used for configuring header/footer correctly.

    The solution here is to provide two closures:

    • dataSource.willDisplayHeader: ((UIView, Int) -> Void)?
    • dataSource.willDisplayFooter: ((UIView, Int) -> Void)?

    I wish we could have better architecture for that than just a properties with closures, but this solution fulfills two most important requirements:

    • provides expected feature
    • don't introduce any breaking change into Static
    opened by rad3ks 4
  • Version 1.0

    Version 1.0

    I'd love to get a release with #60 but that removes functionality. Should the next version be 1.0? There's a few other breaking changes I'd like to make before we 1.0 (order of initializer params, maybe remove UUID from Row).

    Anyway, 1.0 feels like such a big commitment. Are we okay making a breaking change before 1.0 (like CocoaPods :P) and just do 0.3.0 with what's in master and defer the big commitment of 1.0?

    What do you think @eliperkins @ayanonagon @hyperspacemark (and anyone else)?

    question 
    opened by soffes 4
  • Allow replacing the data source in TableViewController

    Allow replacing the data source in TableViewController

    Tested this in the demo app and it all works as expected.

    Built this to make subclassing a bit easier. I'm working on a thing that has a segmented control at the top. Changing the segment changes the data in the table view. This change makes implementing this really easy.

    opened by soffes 4
  • Add support for more modern (non-deprecated) table view swipe API

    Add support for more modern (non-deprecated) table view swipe API

    UITableViewRowAction and it’s associated methods have been deprecated in favor of the new UISwipeActionsConfiguration object which can be configured on the trailing and leading edges of a table view cell.

    This API is available on iOS 11.0 onwards. The cleanest way to support this is to bump the deployment target to iOS 11.

    opened by cgossain 0
  • Still maintained?

    Still maintained?

    There are a number of issues from a couple years ago plus PRs ready for review that haven't been looked at in awhile. Just wondering if this library is still being actively maintained.

    opened by colinhumber 0
  • [Question] Change detailText Without Storing Row

    [Question] Change detailText Without Storing Row

    Hi, I am looking for 1 of these things:

    • A way to set detailText inside selection

    • Another library with the amazing simplicity, but not just for static tables.

        yp.yearSelected.subscribe(onNext: { year in
            self.settings.year = year
            // Set Value Here!
        }).disposed(by: self.disposeBag)
      
        ...Row(text: "Change Year", detailText: year, selection: {
              self.present(yp, animated: true)
        }, accessory: .disclosureIndicator)...
      

    image

    opened by reteps 0
  • Row with SwitchAccessory loses its state after scrolling the table

    Row with SwitchAccessory loses its state after scrolling the table

    Hello!

    I am using a Row with UISwitch as seen in the example project here. However when scrolling down the table and then up again, the switch loses its on state.

    Tested straight from example project:

    Is this due to cell reusing? How can I preserve switch state on scroll?

    Thanks

    EDIT: This is the way I'm using it. Am I doing something wrong?

    var value: Bool = false

    Row(text: "UISwitch", accessory: .switchToggle(value: self.value) { [unowned self] newValue in
         self.value = newValue
    })
    
    opened by n3d1117 10
Releases(v4.0.0)
This framework allows you to build Table views using UIKit with syntax similar to SwiftUI

This framework allows you to build Table views using UIKit with syntax similar to SwiftUI

Fun 60 Dec 17, 2022
Dynamically hide / show cells of static UITableViewController

Dynamically hide / show cells of static UITableViewController, Swift Port of StaticDataTableViewController. Installation CocoaPods pod 'StaticTableVie

muyexi 26 Sep 16, 2022
TableViews - Emoji Table View For iOS With Swift

TableViews Hello! This is EmojiTableView. Let me introduce you my first app when

null 0 Jan 2, 2022
A Swift library for swipeable table cells

BWSwipeRevealCell Using the library **Note: Use version 1.0.1 for Swift 2.3 support and version 2.0.0 or higher for Swift 3 support ** There are two m

Kyle Newsome 67 May 11, 2022
Use Yelp API to fetch restuarants around a location and show them in a table view

Yelp Use Yelp API to fetch restuarants around a location and show them in a table view - Infinite scrolling, Prefetching, Image Caching. Design Patter

null 0 Nov 1, 2021
Using UI Table View

News-App Table View와 Table view controller Table View : Table의 크기를 지정할 수 있다. Table View Controller: 전체의 뷰가 하나의 테이블 Table View Table view 구성요소 결정하기 어떤

Jiwon 0 Dec 9, 2021
Typed, yet Flexible Table View Controller

ConfigurableTableViewController Simple view controller that provides a way to configure a table view with multiple types of cells while keeping type s

Arek Holko 270 Oct 15, 2022
Generic table view controller with external data processing

FlexibleTableViewController Swift library of generic table view controller with external data processing of functionality, like determine cell's reuse

Dmytro Pylypenko 9 May 20, 2018
A UITableView extension that enables cell insertion from the bottom of a table view.

ReverseExtension UITableView extension that enabled to insert cell from bottom of tableView. Concept It is difficult to fill a tableview content from

Taiki Suzuki 1.7k Dec 15, 2022
Elegant and easy way to integrate pagination with dummy views

AZTableView Controller Features Automatic pagination handling No more awkward empty TableView screen AZ TableView controller give you advantage to con

Afroz Zaheer 73 Oct 17, 2022
A simple way to create a UITableView for settings in Swift.

QuickTableViewController A simple way to create a table view for settings, including: Table view cells with UISwitch Table view cells with center alig

Cheng-Yao Lin 525 Dec 20, 2022
PreviewTransition is a simple preview gallery UI controller with animated tranisitions.

PreviewTransition is a simple preview gallery UI controller with animated tranisitions. Swift UI library made by @Ramotion

Ramotion 2.1k Dec 19, 2022
Simple and beautiful stacked UIView to use as a replacement for an UITableView, UIImageView or as a menu

VBPiledView simple but highly effective animation and interactivity! By v-braun - viktor-braun.de. Preview Description Very simple and beautiful stack

Viktor Braun 168 Jan 3, 2023
Simple timeline view implemented by UITableViewCell

TimelineTableViewCell TimelineTableViewCell is a simple timeline view implemented by UITableViewCell. The UI design of TimelineTableViewCell is inspir

Zheng-Xiang Ke 1.3k Dec 25, 2022
Simple single-selection or multiple-selection checklist, based on UITableView

SelectionList Simple single-selection or multiple-selection checklist, based on UITableView. Usage let selectionList = SelectionList() selectionList.i

Yonat Sharon 111 Oct 6, 2022
INTUZ is presenting an interesting a Multilevel Expand/Collapse UITableView App Control to integrate inside your native iOS-based application

INTUZ is presenting an interesting a Multilevel Expand/Collapse UITableView App Control to integrate inside your native iOS-based application. MultilevelTableView is a simple component, which lets you use the tableview with multilevel tree view in your project.

INTUZ 3 Oct 3, 2022
An easy-to-use UITableViewCell subclass that implements a swippable content view which exposes utility buttons (similar to iOS 7 Mail Application)

SWTableViewCell An easy-to-use UITableViewCell subclass that implements a swipeable content view which exposes utility buttons (similar to iOS 7 Mail

Christopher Wendel 7.2k Dec 31, 2022
VTMagic is a page container library for iOS.

VTMagic VTMagic is a page container library for iOS, you can custom every page controller by different identifier if you need. It's so easy to use!(中文

Victor Tian 1.8k Dec 28, 2022