✨ Super sweet syntactic sugar for Swift initializers

Last update: Jun 18, 2022

Then

Swift CocoaPods Build Status

Super sweet syntactic sugar for Swift initializers.

At a Glance

Initialize UILabel then set its properties.

let label = UILabel().then {
  $0.textAlignment = .center
  $0.textColor = .black
  $0.text = "Hello, World!"
}

This is equivalent to:

let label: UILabel = {
  let label = UILabel()
  label.textAlignment = .center
  label.textColor = .black
  label.text = "Hello, World!"
  return label
}()

Tips and Tricks

  • You can use then() to all of NSObject subclasses.

    let queue = OperationQueue().then {
      $0.maxConcurrentOperationCount = 1
    }
  • Want to use with your own types? Just make extensions.

    extension MyType: Then {}
    
    let instance = MyType().then {
      $0.really = "awesome!"
    }
  • Use with() when copying the value types.

    let newFrame = oldFrame.with {
      $0.size.width = 200
      $0.size.height = 100
    }
    newFrame.width // 200
    newFrame.height // 100
  • Use do() to do something with less typing.

    UserDefaults.standard.do {
      $0.set("devxoul", forKey: "username")
      $0.set("[email protected]", forKey: "email")
      $0.synchronize()
    }

Real World Example

Here's an example usage in an UIViewController subclass.

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")
  }

  override func viewDidLoad() {
    super.viewDidLoad()
    self.view.addSubview(self.titleLabel)
    self.view.addSubview(self.tableView)
  }

}

Installation

  • Using CocoaPods:

    pod 'Then'
  • Using Swift Package Manager:

    import PackageDescription
    
    let package = Package(
      name: "MyAwesomeApp",
      dependencies: [
        .Package(url: "https://github.com/devxoul/Then", majorVersion: 2),
      ]
    )

License

Then is under MIT license. See the LICENSE file for more info.

GitHub

https://github.com/devxoul/Then
Comments
  • 1. cannot install through carthage

    *** Skipped building Then due to the error: Dependency "Then" has no shared framework schemes

    Please follow this guide to fix -> https://github.com/Carthage/Carthage#share-your-xcode-schemes

    Reviewed by danjiang at 2016-07-29 08:26
  • 2. lazy code

    lazy var tableView: UITableView = { let tabView =UITableView.init(frame: .zero, style: .plain) tabView.backgroundColor = UIColor.white tabView.dataSource = self tabView.delegate = self return tabView }() I often use lazy loading, and,how to write by Then。Can you give me a test code。

    Reviewed by hanks-hu at 2018-11-01 07:58
  • 3. Add ability to call block on Optional

    Hey!

    I really like then approach and wanted to extend it for optionals. Feature implemented in this PR is different from current Then, however similar in ideology.

    It allows calling any custom block of code on optional, if optional contains .Some. Most common case for this would be [weak self] in various kinds of completion blocks, however there are a lot more cases where you can use this approach.

    For example, let's say we need to use weak self, however pass self somewhere else as unwrapped optional, like this:

    self.doSomethingWithCompletion { [weak self] result in
        self?.parseResult(result, receivedFrom: self!)
        self?.doSomething()
    }
    

    This would require multiple optional unwrappings and possibly even force unwraps. Another way to do this is to unwrap with guard:

    self.doSomethingWithCompletion { [weak self] result in
        guard let strongSelf = self else { return }
        strongSelf.parseResult(result, receivedFrom: strongSelf)
        strongSelf.doSomething()
    }
    

    Unwraps are gone, however we introduced new variable for self, which is not really convenient. Meet Then from this PR:

    self.doSomethingWithCompletion { [weak self] result in
        self.then {
            $0.parseResult(result, receivedFrom: $0)
            $0.doSomething()
        }
    }
    
    Reviewed by DenTelezhkin at 2016-02-04 14:01
  • 4. Added "when", which will only execute when initial condition is met

    I propose we add one more function - when. This serves exactly the same purpose, but "then" is only executed when initial condition is met. This is extremely useful in a lot of cases, as it changes often used syntax

    if (true) {
        label.then {
            ...
        }
    }
    

    to

    label.when(true) {
        ...
    }
    

    The only problem is that it does not fit with name of your repository :D but I think it is okay :)

    Reviewed by JiriTrecak at 2016-01-08 15:06
  • 5. ERROR when upload to AppStore

    ERROR ITMS-90056: "This bundle Payload/X.app/Frameworks/Then.framework is invalid. The Info.plist file is missing the required key: CFBundleVersion."

    Reviewed by devjia at 2017-10-20 14:43
  • 6. How to use this syntax for IBOutlet views?

    Instead of creating a new instance for a view, is there a possibility to fetch the existing instance and set attributes to it? I want to update attributes initially for IBOutlets views.

    Reviewed by dinarajas at 2015-12-29 17:56
  • 7. cocoapods with 'Then' issues

    when I use it with cocoapods ,I will get the issues "Command /bin/sh failed with exit code 1", but not appear other what like "then".it is my pods file:

    platform :ios, '9.0' use_frameworks!

    target 'MapInSwift' do pod 'Alamofire' pod 'SwiftyJSON' pod 'Then', '~> 2.1' end

    if i remove the line with "pod 'Then', '~> 2.1'", i will get no issue

    I fand the solution on the google but no way is fit me.If i need particular setting with Xcode(xcode 8.0; swift 3.0)

    Reviewed by yanjinquan at 2016-10-28 01:37
  • 8. Accessing instance variables in then block

    I can't seem to access class variables in my then block:

    For example

    class GradientView {
       let colors = ...
       lazy var gradientLayer = CAGradientLayer().then {
           $0.colors = self.colors // also tried colors
       }
    }
    

    doesn't work, but

    class GradientView {
       let colors = ...
       lazy var gradientLayer: CAGradientLayer = {
           let layer = CAGradientLayer()
           layer.colors = self.colors
           return layer
       }()
    }
    

    does.

    Can I repeat my old pattern of accessing instance variables in a lazy init using Then?

    Reviewed by AndrewSB at 2016-07-20 00:12
  • 9. [proposal] Implementation of another method without inout

    Problem

    The code below works in Then 1.0.1 but doesn't work in 1.0.2.

    func tempt(label: UILabel) {
        label.text = "I💞Then"
    }
    
    let label1 = UILabel()
    tempt(label1) // Works fine definitely
    UILabel().then(tempt) // Error: Cannot convert value of type '(UILabel) -> ()' to expected argument type 'inout UILabel -> Void'
    

    Adding inout keyword to the func resolves the error, but it brings another problem.

    func temptInOut(inout label: UILabel) {
        label.text = "I💞Then"
    }
    
    UILabel().then(temptInOut) // Works fine
    
    let label2 = UILabel()
    temptInOut(label2) // Error: Cannot convert value of type 'UILabel' to expected argument type 'inout UILabel'
    temptInOut(&label2) // Another Error: Cannot pass immutable value as inout argument: 'label2' is a 'let' constant
    

    To resolve all errors, I should write code as below.

    var label3 = UILabel()
    temptInOut(&label3) // Works fine but seems ugly.
    

    I don't use neither var nor &...

    Proposal

    #18 is nice-to-have modification, but old-style method(without inout keyword) is also nice in some situations.

    So why don't you implement another old-type method as (@noescape block: Self -> Void) -> Self ?

    Reviewed by takasek at 2016-06-01 03:30
  • 10. Strange issue after updating to version 1.0.0

    I got compiling error Cannot convert value of type '_ -> ()' to expected argument type 'inout WKWebView -> Void' with this code

    webView.then {
        $0.navigationDelegate = self
    }
    

    However, the error's gone when there are two assignments in the block

    webView.then {
        $0.navigationDelegate = self
        $0.tag = 1
    }
    
    Reviewed by tuyendv2 at 2016-01-10 14:25
  • 11. Fix for CoreGraphics not being available on Linux

    I'm using this library in a Vapor project which needs to run on Linux and I found that Then won't build on Linux because CoreGraphics isn't available so I've wrapped all CoreGraphics import and all the CG* extensions in #if !os(Linux) checks.

    Reviewed by Noobish1 at 2020-01-24 05:00
  • 12. [proposal] Mutating a value type

    Motivation

    To mutate some deeply nested value types, we have to write the whole key path at least twice:

    some.very[deep].structure.someProperty = someValue
    some.very[deep].structure.anotherProperty = anotherValue
    
    // or with Then:
    
    some.very[deep].structure = some.very[deep].structure.with {
        $0.someProperty = someValue
        $0.anotherProperty = anotherValue
    }
    

    Solution

    Let's extend Then with mutate function (alternatives: update, access, write):

    extension Then {
        public mutating func mutate(_ block: (inout Self) throws -> Void) rethrows {
            try block(&self)
        }
    }
    

    Usage:

    some.very[deep].structure.mutate {
        $0.someProperty = someValue
        $0.anotherProperty = anotherValue
    }
    

    It would be great to have this in Then library. Thank you!

    Reviewed by dtrofimov at 2021-04-27 20:57
  • 13. Is Then dead? (abandon-ware?)

    Has Then been abandoned?  It doesn't appear @devxoul has responded to any issues or PRs, or made any code changes since Sept 2019.  And basically every comment he made before than was highly resistant to making any changes or accommodations for the devs who rely on Then.

    Is it time for someone else to take over the project?  Is there someone else who is already maintaining an updated fork who's willing to take up the mantle of maintaining the community, and who welcomes us all switching over to his/her fork?

    Side-note: I grew tired of some of the issues with Then a while back and wrote my own stab from scratch at solving this problem— I chose to go with a free function approach that's closer to the with keyword in Python, JavaScript, Visual Basic, Object Pascal, Delphi and using in C#, and which seems to be more idiomatic Swift.  I also care about making sure my libraries work in every build toolchain and environment (SPM, CocoaPods, Carthage, Xcode project embedding, etc.); can solve any reasonable user-requested problem (@discardableResult, arbitrary return value, @inlinable, etc.); and can be used freely by everyone (completely copyright-free public domain, no restrictions or attribution needed).  My recently-uploaded library is called With.

    Reviewed by capnslipp at 2020-03-08 16:24
  • 14. Remove xcodeproj & xcshareddata ignores

    The .gitignore file currently is ignoring xcodepoj-related files, which currently does nothing for the Then project because of the decision to go full SPM and remove all xcodeproj stuff (#55).

    However, ignoring these files causes issues when Then's source is included in outer Git repo (via git-subtree or direct copying of project) such as when using Carthage or manual library management in conjunction with a generated xcodeproj (swift package generate-xcodeproj). Because Then's .gitignore is picked up by the enclosing repo, that prevents the generated xcodeproj or shared schemes from being able to be checked-in— which should arguably be under the discretion of the enclosing repo's build setup.  Removed the ignores for xcodeproj and xcshareddata to fix this, and removed the xcuserdata line too for good measure (again, if there's no xcodeproj in Then, there's no need to ignore it).

    Reviewed by capnslipp at 2020-02-25 11:06
  • 15. carthage build

    $carthage update --platform macOS results in:

    *** Skipped building Then due to the error: Dependency "Then" has no shared framework schemes for any of the platforms: Mac

    If you believe this to be an error, please file an issue with the maintainers at https://github.com/devxoul/Then/issues/new

    Using carthage 0.34, Swift 5, xcode 10.2

    Reviewed by hk05 at 2019-05-11 22:39
🍯 Syntactic sugar for Moya

MoyaSugar Syntactic sugar for Moya. Why? Moya is an elegant network abstraction layer which abstracts API endpoints gracefully with enum. However, it

May 31, 2022
Swift's Sugar. Heavily inspired on Objc Sugar

Swift's Sugar. Heavily inspired on Objc Sugar

Jan 29, 2022
📦 KeyPath dynamicMemberLookup based syntax sugar for Swift.

DuctTape ?? KeyPath dynamicMemberLookup based syntax sugar for Swift. let label: UILabel = UILabel().ductTape .numberOfLines(0) .textColor(.re

May 15, 2022
SharkUtils is a collection of Swift extensions, handy methods and syntactical sugar that we use within our iOS projects at Gymshark.

SharkUtils is a collection of Swift extensions, handy methods and syntactical sugar that we use within our iOS projects at Gymshark.

Jul 6, 2021
Sugar is a sweetener for your Cocoa implementations.
Sugar is a sweetener for your Cocoa implementations.

Sugar is a sweetener for your Cocoa implementations. Table of Contents iOS Application Screen Simulator Keyboard Observer iOS Extensions UIView

Jun 18, 2022
Synatax sugar for Measurement of Foundation.

WrappedMeasurement 2022 © Weizhong Yang a.k.a zonble Syntax sugar for NSMeasurement of Foundation. NSMeasurement and NSUnit compose a great tool to le

Jan 25, 2022
HumanMeasurementSwift - Synatax sugar for Measurement of Foundation

HumanMeasurement 2022 © Weizhong Yang a.k.a zonble Syntax sugar for NSMeasuremen

Jan 25, 2022
Extensions giving Swift's Codable API type inference super powers 🦸‍♂️🦹‍♀️
Extensions giving Swift's Codable API type inference super powers 🦸‍♂️🦹‍♀️

Welcome to Codextended — a suite of extensions that aims to make Swift’s Codable API easier to use by giving it type inference-powered capabilities an

Jun 17, 2022
Super powerful remote config utility written in Swift (iOS, watchOS, tvOS, OSX)
Super powerful remote config utility written in Swift (iOS, watchOS, tvOS, OSX)

Mission Control Super powerful remote config utility written in Swift (iOS, watchOS, tvOS, OSX) Brought to you by Have you ever wished you could chang

Apr 28, 2022
BCSwiftTor - Opinionated pure Swift controller for Tor, including full support for Swift 5.5 and Swift Concurrency

BCSwiftTor Opinionated pure Swift controller for Tor, including full support for

May 20, 2022
Swift Markdown is a Swift package for parsing, building, editing, and analyzing Markdown documents.

Swift Markdown is a Swift package for parsing, building, editing, and analyzing Markdown documents.

Jun 27, 2022
Swift-DocC is a documentation compiler for Swift frameworks and packages aimed at making it easy to write and publish great developer documentation.

Swift-DocC is a documentation compiler for Swift frameworks and packages aimed at making it easy to write and publish great developer docum

Jun 22, 2022
Cross-Platform, Protocol-Oriented Programming base library to complement the Swift Standard Library. (Pure Swift, Supports Linux)

SwiftFoundation Cross-Platform, Protocol-Oriented Programming base library to complement the Swift Standard Library. Goals Provide a cross-platform in

Jun 10, 2022
Swift - ✏️Swift 공부 저장소✏️

Swift 스위프트의 기초 1. Swift의 기본 2. 변수와 상수 [3. 데이터 타입 기본] [4. 데이터 타입 고급] 5. 연산자 6. 흐름 제어 7. 함수 8. 옵셔널 객체지향 프로그래밍과 스위프트 9. 구조체와 클래스 10. 프로퍼티와 메서드 11. 인스턴스 생

Mar 9, 2022
Swift-ndi - Swift wrapper around NewTek's NDI SDK

swift-ndi Swift wrapper around NewTek's NDI SDK. Make sure you extracted latest

Jun 17, 2022
__.swift is a port of Underscore.js to Swift.

__.swift Now, __.swift is version 0.2.0! With the chain of methods, __.swift became more flexible and extensible. Documentation: http://lotz84.github.

Jan 29, 2022
SNTabBarDemo-Swift - Cool TabBar With Swift
SNTabBarDemo-Swift - Cool TabBar With Swift

SNTabBarDemo-Swift Cool TabBar How To Use // MARK: - setup private func setu

Apr 6, 2022
Swift-when - Expression switch support in Swift

Swift When - supporting switch expressions in Swift! What is it? Basically, it a

Jan 24, 2022
Swift-compute-runtime - Swift runtime for Fastly [email protected]

swift-compute-runtime Swift runtime for Fastly [email protected] Getting Started Crea

Jun 15, 2022