Then: Swift initializer sugar that replaces the closure-immediately-invoked pattern
✨ Super sweet syntactic sugar for Swift initializers
At a glance
- What is it?
- Then is a small Swift library that adds then, with and do helpers to NSObject subclasses and any type you extend, so you can configure an object at creation instead of writing a closure and calling it. It is for Swift developers who configure UIKit views and other objects in code.
- Who is it for?
- Then is worth adopting if your codebase has many closure-wrapped initializers for UIKit views, view controllers or other NSObject subclasses, and you want the configured object back in one expression. It is the wrong tool if your project avoids NSObject inheritance, if you prefer initializer parameters over post-creation assignment, or if you cannot accept a dependency whose last release, 3.0.0, dates to 2022-04-26 even though the repository's last push was on 2026-03-10.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Activity is slowing. The repository last received commits 6 months ago.
- What is it written in?
- Mainly Swift, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The closure-and-call pattern Then removes
Swift has no built-in way to create an object and set several properties on it in one expression. The common workaround is a closure that is declared and immediately invoked, which returns the configured object. The README shows the full form: a typed let binding, a closure body that instantiates the object, assigns textAlignment, textColor and text, and returns it, followed by the call operator.
That pattern works, but it costs a type annotation, a return statement, a pair of braces and a trailing call for every configured object. Then replaces it with a single method call whose trailing closure receives the object as $0. The README's first example configures a UILabel with textAlignment, textColor and text in one then block, and the README states the two forms are equivalent. The library is aimed at Swift developers who write view setup in code rather than in Interface Builder, and who want the assignment statements grouped at the point of creation.
How then, with and do differ in what they return
The mechanism is protocol conformance plus a generic extension. The README says you can use then() on all NSObject subclasses, and that to use it with your own types you make an extension conforming that type to Then. Because the method is generic over the receiver, the closure parameter is typed as the concrete type, so $0.textAlignment on a UILabel resolves without a cast.
The three helpers are not interchangeable. then() is for reference types and returns the same instance after mutation. with() is documented for copying value types: the README's CGRect example assigns size.width and size.height inside with, then reads newFrame.width and newFrame.height and comments the results as 200 and 100. That means with produces a new value rather than mutating in place, which is the correct semantics for a struct but would be surprising if you expected the original to change. do() is the shortest form and is shown for side effects on an existing object: the README example calls UserDefaults.standard.do and sets a username and an email before calling synchronize. If you do not need the object back, do() avoids the assignment on the left-hand side.
Installing Then with CocoaPods or Swift Package Manager
The README lists two installation routes. With CocoaPods, the pod line goes in your Podfile. The README gives it without a version constraint:
pod 'Then'After running pod install, the pod should appear in your workspace and you can import Then in any file that configures objects. The README also points at the CocoaPods page for the pod, and the repository carries a Then.podspec at the top level, so the podspec is checked in rather than generated elsewhere.
The Swift Package Manager route is declared in the package manifest. The README's snippet uses the older .Package spelling with a majorVersion argument, which is the syntax from an earlier Swift tools generation:
import PackageDescription
let package = Package(
name: "MyAwesomeApp",
dependencies: [
.Package(url: "https://github.com/devxoul/Then", majorVersion: 2),
]
)If your manifest targets a newer tools version, you will need the current product-and-package form instead, because the README snippet has not been updated to it. Note also that the snippet pins major version 2 while the most recent release listed is 3.0.0, so check which major version you actually want before copying it.
For a first real use, take the README's view controller example. Inside a UIViewController subclass, declare a label property with then and set its color and alignment, and declare a table view with then to clear its background, remove separators and register a cell class:
final class MyViewController: UIViewController {
let titleLabel = UILabel().then {
$0.textColor = .black
$0.textAlignment = .center
}
let tableView = UITableView().then {
$0.backgroundColor = .clear
$0.separatorStyle = .none
$0.register(MyCell.self, forCellReuseIdentifier: "myCell")
}
}The two properties are configured at the point of declaration, and viewDidLoad only needs to add them as subviews. If the code compiles, the closure parameter is already the right type and no downcast is present.
Where Then stops being the right tool
The NSObject requirement is the main boundary. The README says then() works on all NSObject subclasses and that other types need an explicit conformance extension. If your model layer is built from structs and enums with no NSObject ancestry and you do not want to add conformance, Then gives you nothing there. The conformance extension is one line per type, but it is still a line you own and must keep, and it is easy to forget when a new type appears.
The value-type behaviour is the second trap. with() returns a modified copy, so code that reads the original after calling with will see the old values. For CGRect that is usually what you want, but the method name gives no hint that a copy is involved, and a developer who has internalised then() as "mutate and return the same instance" may assume with() does the same. The README documents the copy semantics through the example output comments rather than in prose.
Finally, the release history is thin. The most recent release listed is 3.0.0 from 2022-04-26, with 2.7.0 in 2020 and 2.6.0 in 2019. The repository's last push was on 2026-03-10, so there is activity on the default branch, but there has been no tagged release in over four years. If your policy requires a recent release tag, Then will not satisfy it on that measure alone.
Then against writing the closure yourself
The honest alternative is not another library. It is the immediately-invoked closure the README shows in its second example: declare the variable with an explicit type, write the closure, instantiate inside it, assign properties, return the instance, and call the closure. That approach has no dependency, works on any type including structs, and is understood by anyone who reads Swift.
The difference in approach is where the configuration lives. With the closure form, the assignments sit inside a function body that the reader has to scan to find the return. With Then, the assignments sit inside a trailing closure attached to the initializer call, and the compiler infers the parameter type from the receiver. The closure form also lets you run arbitrary statements, declare local variables and branch before returning, which a trailing closure can do as well, so the real saving is the type annotation, the return and the call operator on every site. Whether that is worth a dependency depends on how many sites you have. In a codebase with dozens of configured views, the reduction is visible; in one with a handful, the closure form is fine.
Maintenance, versioning and the MIT licence
Then is MIT licensed, and the README points to the LICENSE file for the full text. MIT is permissive: it allows use in closed-source products provided the copyright notice and permission notice are retained, but this is a summary of the licence identifier and not legal advice. Check the LICENSE file in the repository for the exact terms before you rely on them.
The upgrade cost is low in absolute terms, because the API surface is three methods. The friction is version drift. The Swift Package Manager snippet in the README pins major version 2 while the newest release listed is 3.0.0, so a project that copies the snippet verbatim will not get the current major version. The repository also contains a Project.swift and a Tuist.swift alongside Package.swift and Then.podspec, which suggests the project is built with Tuist in addition to being distributed as a package and a pod; that matters if you plan to build the library from source rather than consume a release. There is no documented rollback procedure in the README, so plan your pinning before you upgrade.
Editorial conclusion
Then is worth adopting if your codebase has many closure-wrapped initializers for UIKit views, view controllers or other NSObject subclasses, and you want the configured object back in one expression. It is the wrong tool if your project avoids NSObject inheritance, if you prefer initializer parameters over post-creation assignment, or if you cannot accept a dependency whose last release, 3.0.0, dates to 2022-04-26 even though the repository's last push was on 2026-03-10. Before you adopt it, verify that the package resolves under your Swift toolchain with the Swift Package Manager declaration below, and confirm the CocoaPods podspec in Then.podspec matches the version you pin.
Frequently asked questions
Does Then work with my own Swift types, or only with NSObject subclasses?
The README states that then() can be used with all NSObject subclasses, and that for your own types you add an extension making the type conform to Then. After that conformance, the same then block syntax applies to that type.
What is the difference between then() and with() in Then?
then() configures a reference type and returns the same instance. with() is documented for copying value types: the README's CGRect example sets size.width and size.height inside with, and the resulting newFrame reads back as 200 and 100, so with produces a modified copy rather than mutating the original.
How do I install Then in a Swift project?
The README lists CocoaPods, where you add the pod 'Then' line to your Podfile, and the Swift Package Manager, where you add the package dependency to your manifest. The manifest snippet in the README uses the older .Package spelling with majorVersion: 2, so check it against your tools version and the 3.0.0 release.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/devxoul-then)