Reusable
A Swift mixin for reusing views easily and in a type-safe way (UITableViewCells, UICollectionViewCells, custom UIViews, ViewControllers, Storyboards…)
Install / Use
/learn @AliSoftware/ReusableREADME
Reusable
<p align="center"> <img alt="Reusable" src="Logo.png" width="150" height="150"/> </p>A Swift mixin to use UITableViewCells, UICollectionViewCells and UIViewControllers in a type-safe way, without the need to manipulate their String-typed reuseIdentifiers. This library also supports arbitrary UIView to be loaded via a XIB using a simple call to loadFromNib()
Installation
<details><summary><b>Requirements</b>: which Reusable version to use for each Swift Version?</summary>| Swift Version | Reusable Version | |----------------|--------------------| | 2.2 & 2.3 | 2.5.1 | | 3.0 (†) | 3.0.0 + | | 4.0 | 4.0.2 + | | 5.0 | 4.1.0 + |
(†) The Reusable 3.0 code also compiles with Swift 4, you'll need 4.0.2+ only if you're using Carthage for integration
</details>Reusable can be integrated to your Xcode projects using one of the following options:
<details><summary>Installation instructions for <b>Swift Package Manager (SPM)</b></summary>Swift Package Manager is Apple's decentralized dependency manager to integrate libraries to your Swift projects. It is now fully integrated with Xcode 11
To integrate Reusable into your project using SPM, specify it in your Package.swift file:
let package = Package(
…
dependencies: [
.package(url: "https://github.com/AliSoftware/Reusable.git", from: "4.1.0"),
],
targets: [
.target(name: "YourTarget", dependencies: ["Reusable", …])
…
]
)
</details>
<details><summary>Installation instructions for <b>Carthage</b></summary>
Carthage is a decentralized dependency manager to add pre-built frameworks to your Cocoa application.
To integrate Reusable into your Xcode project using Carthage, specify it in your Cartfile:
github "AliSoftware/Reusable"
Then run carthage update --use-xcframeworks
CocoaPods is a dependency manager to automate integration of frameworks to your Swift and Objective-C Cocoa projects.
To integrate Reusable into your Xcode project using Cocoapods, specify it in your Podfile:
pod 'Reusable'
</details>
Introduction
This library aims to make it super-easy to create, dequeue and instantiate reusable views anywhere this pattern is used: from the obvious UITableViewCell and UICollectionViewCell to custom UIViews, even supporting UIViewControllers from Storyboards.
All of that simply by marking your classes as conforming to a protocol, without having to add any code, and creating a type-safe API with no more String-based API.
// Example of what Reusable allows you to do
final class MyCustomCell: UITableViewCell, Reusable { /* And that's it! */ }
tableView.register(cellType: MyCustomCell.self)
let cell: MyCustomCell = tableView.dequeueReusableCell(for: indexPath)
This concept, called a Mixin (a protocol with default implementation for all its methods), is explained here in my blog post in details.
Table of Contents
- Type-safe cells
- Type-safe XIB-based reusable views
- Type-safe ViewControllers from Storyboards
- Additional tips
- Example project
- Talks and Articles about Reusable
- License
Type-safe UITableViewCell / UICollectionViewCell
✍️ Examples and explanations below use
UITableViewandUITableViewCell, but the exact same examples and explanations apply forUICollectionViewandUICollectionViewCell.
1. Declare your cells to conform to Reusable or NibReusable
- Use the
Reusableprotocol if they don't depend on a NIB (this will useregisterClass(…)to register the cell) - Use the
NibReusabletypealias (=Reusable & NibLoadable) if they use aXIBfile for their content (this will useregisterNib(…)to register the cell)
final class CustomCell: UITableViewCell, Reusable { /* And that's it! */ }
<details> <summary>📑 Example for a Code-based custom tableView cell</summary>✍️ Notes
- For cells embedded in a Storyboard's tableView, either one of those two protocols will work (as you won't need to register the cell manually anyway, since registration is handled by the storyboard automatically)
- If you create a XIB-based cell, don't forget to set its Reuse Identifier field in Interface Builder to the same string as the name of the cell class itself.
- 💡
NibReusableis a typealias, so you could still use two protocols conformanceReusable, NibLoadableinstead ofNibReusable.
final class CodeBasedCustomCell: UITableViewCell, Reusable {
// By default this cell will have a reuseIdentifier of "CodeBasedCustomCell"
// unless you provide an alternative implementation of `static var reuseIdentifier`
// No need to add anything to conform to Reusable. You can just keep your normal cell code
@IBOutlet private weak var label: UILabel!
func fillWithText(text: String?) { label.text = text }
}
</details>
<details>
<summary>📑 Example for a Nib-based custom tableView cell</summary>
final class NibBasedCustomCell: UITableViewCell, NibReusable {
// or
// final class NibBasedCustomCell: UITableViewCell, Reusable, NibLoadable {
// Here we provide a nib for this cell class (which, if we don't override the protocol's
// default implementation of `static var nib: UINib`, will use a XIB of the same name as the class)
// No need to add anything to conform to Reusable. You can just keep your normal cell code
@IBOutlet private weak var pictureView: UIImageView!
func fillWithImage(image: UIImage?) { pictureView.image = image }
}
</details>
<details>
<summary>📑 Example for a Code-based custom collectionView cell</summary>
// A UICollectionViewCell which doesn't need a XIB to register
// Either because it's all-code, or because it's registered via Storyboard
final class CodeBasedCollectionViewCell: UICollectionViewCell, Reusable {
// The rest of the cell code goes here
}
</details>
<details>
<summary>📑 Example for a Nib-based custom collectionView cell</summary>
// A UICollectionViewCell using a XIB to define it's UI
// And that will need to register using that XIB
final class NibBasedCollectionViewCell: UICollectionViewCell, NibReusable {
// or
// final class NibBasedCollectionViewCell: UICollectionViewCell, Reusable, NibLoadable {
// The rest of the cell code goes here
}
</details>
2. Register your cells
Unless you've prototyped your cell in a Storyboard, you'll have to register the cell class or Nib by code.
To do this, instead of calling registerClass(…) or registerNib(…) using a String-based reuseIdentifier, just call:
tableView.register(cellType: theCellClass.self)
<details>
<summary>📑 Example of `UITableView` registration</summary>
class MyViewController: UIViewController {
@IBOutlet private weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// This will register using the class (via `register(AnyClass?, forCellReuseIdentifier: String)`)
// because the CodeBasedCustomCell type conforms to Reusable, but not NibLoadable (nor the NibReusable typealias)
tableView.register(cellType: CodeBasedCustomCell.self)
// This will register using NibBasedCustomCell.xib (via `register(UINib?, forCellReuseIdentifier: String)`)
// because the NibBasedCustomCell type conforms to NibLoadable (via the NibReusable typealias)
tableView.register(cellType: NibBasedCustomCell.self)
}
}
</details>
3. Dequeue your cells
To dequeue a cell (typically in your cellForRowAtIndexPath implementation), simply call dequeueReusableCell(indexPath:):
// Either
let cell = tableView.dequeueReusableCell(for: indexPath) as MyCustomCell
// Or
let cell: MyCustomCell = tableView.dequeueReusableCell(for: indexPath)
As long as Swift can use type-inference to understand that you'll want a cell of type MyCustomCell (either using as MyCustomCell or explicitly typing the receiving variable cell: MyCustomCell), it will magically infer both the cell class to use and thus its reuseIdentifier needed to dequeue the cell, and which exact type to return to save you a type-cast.
- No need for you to manipulate
reuseIdentifiersStrings manually anymore! - No need to force-cast the returned
UITableViewCellinstance down to yourMyCustomCellclass either!
extension MyViewController: UITableViewDataSource {
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell = tabl
Related Skills
node-connect
330.3kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
81.3kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
330.3kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
commit-push-pr
81.3kCommit, push, and open a PR


