JMStaticContentTableViewController
A subclass-able way to cleanly and neatly implement a table view controller much like those in Settings.app, with nice-looking fields to collect or display information, all using a simple and convienent block-based syntax.
Install / Use
/learn @jakemarsh/JMStaticContentTableViewControllerREADME
JMStaticContentTableViewController
A simple way to build Settings-style screens for iOS apps.
JMStaticContentTableViewController allows you to easily and simply display "static content" like iOS Settings, About screens, Login forms, or any screen that displays or collects information in a table format.
Originally built with blocks in Objective-C, now fully rewritten in Swift with both UIKit and SwiftUI support.
Features
- Declarative API - Build table views with simple, readable code
- UIKit Support -
JMStaticContentTableViewControllersubclass - SwiftUI Support -
JMStaticContentListview component - Built-in Cell Types - Text, toggle, value display cells
- Section Management - Add, insert, remove sections with animations
- Custom Cells - Use any
UITableViewCellsubclass - Backward Compatible - Original Objective-C API still works
- Thread-safe - All operations properly synchronize with the table view
Requirements
- iOS 15.0+ / macOS 12.0+ / tvOS 15.0+
- Swift 5.9+
- Xcode 15.0+
For older iOS versions (5.0-14.x), use the legacy Objective-C implementation included in this repo.
Installation
Swift Package Manager (Recommended)
Add JMStaticContentTableViewController to your project via SPM:
dependencies: [
.package(url: "https://github.com/jakemarsh/JMStaticContentTableViewController.git", from: "2.0.0")
]
Or in Xcode: File → Add Package Dependencies → Enter the repository URL.
CocoaPods (Legacy)
pod 'JMStaticContentTableViewController'
Quick Start
Swift (UIKit)
import JMStaticContentTableViewController
class SettingsViewController: JMStaticContentTableViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Add an Account section
addSection { section, _ in
section.headerTitle = "Account"
// Navigation cell
section.addCell(.text("Profile", onSelect: { [weak self] _ in
self?.navigationController?.pushViewController(ProfileViewController(), animated: true)
}))
// Toggle cell
section.addCell(.toggle("Notifications", isOn: true) { isOn in
UserDefaults.standard.set(isOn, forKey: "notifications")
})
// Value display cell
section.addCell(.value("Version", value: "2.0.0"))
}
// Add an About section
addSection { section, _ in
section.headerTitle = "About"
section.footerTitle = "Thanks for using our app!"
section.addCell(.text("Terms of Service", onSelect: { _ in
// Open terms
}))
}
}
}
SwiftUI
import JMStaticContentTableViewController
struct SettingsView: View {
@State private var notificationsEnabled = true
var body: some View {
NavigationView {
JMStaticContentList {
JMStaticContentListSection(header: "Account") {
JMStaticContentListRow("Profile", systemImage: "person.circle") {
ProfileView()
}
JMStaticContentListToggle("Notifications", isOn: $notificationsEnabled)
JMStaticContentListRow("Version", value: "2.0.0")
}
JMStaticContentListSection(header: "About", footer: "Thanks for using our app!") {
JMStaticContentListRow("Terms of Service") {
// Handle tap
}
}
}
.navigationTitle("Settings")
}
}
}
Objective-C (Legacy)
#import "JMStaticContentTableViewController.h"
- (void)viewDidLoad {
[super viewDidLoad];
[self addSection:^(JMStaticContentTableViewSection *section, NSUInteger sectionIndex) {
section.headerTitle = @"Account";
[section addCell:^(JMStaticContentTableViewCell *staticContentCell, UITableViewCell *cell, NSIndexPath *indexPath) {
staticContentCell.cellStyle = UITableViewCellStyleValue1;
cell.textLabel.text = @"Wi-Fi";
cell.detailTextLabel.text = @"Connected";
} whenSelected:^(NSIndexPath *indexPath) {
[self.navigationController pushViewController:[[WifiViewController alloc] init] animated:YES];
}];
}];
}
Cell Types
Text Cell
// Simple text
section.addCell(.text("Label"))
// With subtitle
section.addCell(.text("Label", detailText: "Subtitle"))
// With image
section.addCell(.text("Label", image: UIImage(systemName: "star")))
// With selection handler
section.addCell(.text("Label", onSelect: { indexPath in
// Handle selection
}))
Toggle Cell
section.addCell(.toggle("Enable Feature", isOn: currentValue) { newValue in
// Handle toggle change
})
Value Cell
section.addCell(.value("Version", value: "2.0.0"))
Custom Cell
let cell = JMStaticContentCell(
reuseIdentifier: "CustomCell",
cellClass: MyCustomCell.self,
height: 80
)
cell.configureBlock = { cellConfig, tableViewCell, indexPath in
guard let customCell = tableViewCell as? MyCustomCell else { return }
customCell.configure(with: myData)
}
cell.whenSelectedBlock = { indexPath in
// Handle selection
}
section.addCell(cell)
Section Management
// Add a section
addSection { section, index in
section.headerTitle = "New Section"
// Add cells...
}
// Insert a section at a specific index
insertSection({ section, index in
// Configure section...
}, at: 1, animated: true)
// Remove a section
removeSection(at: 0, animated: true)
// Remove all sections
removeAllSections()
// Reload a section
reloadSection(at: 0, animated: true)
Migration from v1.x (Objective-C)
The Swift rewrite maintains API compatibility. Most Objective-C code will continue to work. For Swift projects:
| Old API (Obj-C) | New API (Swift) |
|-----------------|-----------------|
| [self addSection:^...] | addSection { section, index in ... } |
| section.headerTitle = @"Title" | section.headerTitle = "Title" |
| [section addCell:^... whenSelected:^...] | section.addCell(.text("Label", onSelect: { ... })) |
| [self removeAllSections] | removeAllSections() |
How It Works
Images can be in three states when you add them:
- Configure Block - Called each time the cell is displayed, configure the UITableViewCell here
- When Selected Block - Called when the user taps the cell, handle navigation or actions here
- Automatic Cell Reuse - Cells are automatically dequeued and reused based on the reuse identifier
Demo App
The repository includes a Settings example app demonstrating typical usage patterns like:
- Wi-Fi network selection with animated row insertion
- Toggle controls for settings
- Navigation between screens
- Section headers and footers
License
JMStaticContentTableViewController is available under the MIT license. See the LICENSE file for details.
Author
Jake Marsh (@jakemarsh)
Originally created in 2011, rewritten in Swift in 2024.
Related Skills
qqbot-channel
346.4kQQ 频道管理技能。查询频道列表、子频道、成员、发帖、公告、日程等操作。使用 qqbot_channel_api 工具代理 QQ 开放平台 HTTP 接口,自动处理 Token 鉴权。当用户需要查看频道、管理子频道、查询成员、发布帖子/公告/日程时使用。
docs-writer
100.1k`docs-writer` skill instructions As an expert technical writer and editor for the Gemini CLI project, you produce accurate, clear, and consistent documentation. When asked to write, edit, or revie
model-usage
346.4kUse CodexBar CLI local cost usage to summarize per-model usage for Codex or Claude, including the current (most recent) model or a full model breakdown. Trigger when asked for model-level usage/cost data from codexbar, or when you need a scriptable per-model summary from codexbar cost JSON.
Design
Campus Second-Hand Trading Platform \- General Design Document (v5.0 \- React Architecture \- Complete Final Version)1\. System Overall Design 1.1. Project Overview This project aims t
