Function

Function

A function (also called a procedure, method, subroutine, or routine) is a portion of code intended to carry out a single, specific task. Use this topic for questions which specifically involve creating or calling functions.

Type Stable & Efficient Wrapper Of Arbitrary Functions

FunctionWrappers.jl: Type stable and efficient wrapper of arbitrary functions

Limitations

Does not handle more than 128 arguments without jlcall wrapper

128 is an arbitrary limit. Should be high enough for all practical cases

Does not support vararg argument types

Wrapper Object cannot be serialized by dump.c and therefore the precompilation of FunctionWrappers is done using a runtime branch and by making the wrapper type mutable.

Compared to @cfunction

This does not require LLVM trampoline support, which is not currently supported by LLVM on all the architectures julia runs on (JuliaLang/julia27174). Other than this issue @cfunction should cover all of the use cases.

Simple Usage Example

using FunctionWrappers
import FunctionWrappers: FunctionWrapper

# For a function that sends (x1::T1, x2::T2, ...) -> ::TN, you use
# a FunctionWrapper{TN, Tuple{T1, T2, ...}}.
struct TypeStableStruct 
  fun::FunctionWrapper{Float64, Tuple{Float64, Float64}}
  second_arg::Float64
end

evaluate_strfun(str, arg) = str.fun(arg, str.second_arg)

example = TypeStableStruct(hypot, 1.0)

@code_warntype evaluate_strfun(example, 1.5) # all good

Proof of principle implementation of JuliaLang/julia13984.

Download Details:

Author: Yuyichao
Source Code: https://github.com/yuyichao/FunctionWrappers.jl 
License: View license

#julia #function #wrapper 

Type Stable & Efficient Wrapper Of Arbitrary Functions
Yvonne  Hickle

Yvonne Hickle

1662610320

Mockit: A Tasty Mocking Framework for Unit Tests in Swift 5.0

Mockit

Introduction

Mockit is a Tasty mocking framework for unit tests in Swift 5.0. It's at an early stage of development, but its current features are almost completely usable.

Mockit is a mocking framework that tastes brilliant. It lets you write beautiful tests with a clean & simple API. Tests written using Mockit are very readable and they produce clean verification errors. It's inspired by the famous mocking framework for Java - Mockito.

Documentation

Mockit is yet to be documented fully but it comes with a sample project that lets you try all its features and become familiar with the API. You can find it in Mockit.xcworkspace.

There's an example test file called ExampleTests.swift. Look there for some tests that can be run. This tests a class Example against a mocked collaborator ExampleCollaborator.

File an issue if you have any question.

To run the example project, clone the repo, and run pod install from the Example directory first.

Limitations

  • There's some boiler-plate code needed to create mocks. See MockExampleCollaborator for an example in the Basic Usage section below. However, a plugin development is on its way for both Xcode and AppCode to minimize writing this boiler-plate code every time a mock needs to be created.

Features

Stubbing. Mockit lets you stub a method and then perform any of 3 actions (thenReturn, thenDo, thenAnswer) individually or in any order via chaining;

Mocking. You can create a subclass extending the Mock protocol to mock required methods;

Call Verification. You can verify method calls using one of 8 supported modes (Once, AtLeastOnce, AtMostOnce, Times, AtLeastTimes, AtMostTimes, Never and Only);

Arguments of specific call. Mockit allows you to obtain the arguments of a specific method call to use custom assertions on them;

Helpful messages. If method verification fails or something goes wrong, Mockit provides readable messages that describes the issue;

Default Type matchers. Out of the box, Mockit can match the following types:

  • String / String?
  • Bool / Bool?
  • Int / Int?
  • Double / Double?
  • Float / Float?
  • Array / Array? of the above primitive types
  • Dictionary / Dictionary? of the above primitive types

Given that Swift does not have reflection, Mockit cannot magically match your custom types, so you need to subclass TypeMatcher protocol to write your one custom type matcher. For an example, see the Basic Usage section below.

Basic Usage

The examples below assume we are mocking this class:

class ExampleCollaborator {

    func voidFunction() {
    }

    func function(int: Int, _ string: String) -> String {
      return ""
    }

    func stringDictFunction(dict: [String: String]) -> String {
      return ""
    }

}

In your test code, you'll need to create a MockExampleCollaborator, which extends ExampleCollaborator and adopts Mock. The mock creates a CallHandler, and forwards all calls to it:

class MockExampleCollaborator: ExampleCollaborator, Mock {

    let callHandler: CallHandler

    init(testCase: XCTestCase) {
      callHandler = CallHandlerImpl(withTestCase: testCase)
    }

    func instanceType() -> MockExampleCollaborator {
      return self
    }

    override func voidFunction() {
      callHandler.accept(nil, ofFunction: #function, atFile: #file, inLine: #line, withArgs: nil)
    }

    override func function(int: Int, _ string: String) -> String {
      return callHandler.accept("", ofFunction: #function, atFile: #file, inLine: #line, withArgs: int, string) as! String
    }

    override func stringDictFunction(dict: Dictionary<String, String>) -> String {
      return callHandler.accept("", ofFunction: #function, atFile: #file, inLine: #line, withArgs: dict) as! String
    }

}

To write a custom type matcher:

public class CustomMatcher: TypeMatcher {

    public func match(argument arg: Any, withArgument withArg: Any) -> Bool {
      switch (arg, withArg) {
        case ( _ as CustomType, _ as CustomType):
          // custom matching code here
          return true
        default:
          return false
      }
    }

}

It is good practice to put the mock objects and custom type matchers in a separate group in the test part of your project.

Currently-supported syntax

// stub a call on a method with parameters, then return value
mockCollaborator.when().call(withReturnValue: mockCollaborator.function(42, "frood")).thenReturn("hoopy")
// stub a call on a method with dictionary parameter, then answer value
mockCollaborator.when().call(withReturnValue: mockCollaborator.stringDictFunction(["Hello": "Pong"])).thenAnswer {
      (args: [Any?]) -> String in

      // custom code here
    }
// stub a call on a void method , then do action
mockCollaborator.when().call(withReturnValue: mockCollaborator.voidFunction()).thenDo {
      (args: [Any?]) -> Void in

      // if the call is received, this closure will be executed
      print("===== thenDo closure called =====")
    }
// stub a call on a method , then return values on multiple calls
mockCollaborator.when().call(withReturnValue: mockCollaborator.stringDictFunction(["Hello": "Pong"])).thenReturn("ping", "hoopy")
// stub a call on a method , then chain multiple actions for corresponding calls
mockCollaborator.when().call(withReturnValue: mockCollaborator.stringDictFunction(["Hello": "Pong"])).thenReturn("ping", "hoopy").thenAnswer {
      (args: [Any?]) -> String in

      // custom code here
    }
// call a method and then get arguments of a specific call which can be asserted later
systemUnderTest.doSomethingWithParamters(42, "frood")
systemUnderTest.doSomethingWithParamters(18, "hoopy")

let argumentsOfFirstCall = mockCollaborator.getArgs(callOrder: 1).of(mockCollaborator.function(AnyValue.int, AnyValue.string))
let argumentsOfSecondCall = mockCollaborator.getArgs(callOrder: 2).of(mockCollaborator.function(AnyValue.int, AnyValue.string))

With nice mocks, Mockit supports the "verify expectations after mocking" style using 8 supported verification modes

// call method on the system under test
systemUnderTest.expectMethodOneAndThree()

// Then
mockCollaborator.verify(verificationMode: Once()).methodOne()
mockCollaborator.verify(verificationMode: Never()).methodTwo()
mockCollaborator.verify(verificationMode: Once()).methodThree()


// call method on the system under test
sut.expectMethodOneTwice()

// Then
mockCollaborator.verify(verificationMode: Times(times: 2)).methodOne()


// call method on the system under test
sut.expectOnlyMethodThree()

// Then
mockCollaborator.verify(verificationMode: Only()).methodThree()


// call method on system under test
sut.expectAllThreeMethods()

// Then
mockCollaborator.verify(verificationMode: Once()).methodOne()
mockCollaborator.verify(verificationMode: AtLeastOnce()).methodTwo()
mockCollaborator.verify(verificationMode: AtMostOnce()).methodThree()


// call method on the system under test
sut.expectMethodTwoAndThree()

// Then
mockCollaborator.verify(verificationMode: AtLeastTimes(times: Times(times: 1))).methodTwo()
mockCollaborator.verify(verificationMode: Never()).methodOne()
mockCollaborator.verify(verificationMode: AtMostTimes(times: Times(times: 3))).methodThree()

Requirements

  • Xcode 9+
  • XCTest

Installation

Mockit is built with Swift 5.0.

CocoaPods

Mockit is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod 'Mockit', '1.5.0'

Manually

  1. Download and drop /Mockit folder in your project.
  2. Congratulations!

Feedback

Issues and pull-requests are most welcome - especially about improving the API further.

Author

Syed Sabir Salman-Al-Musawi, sabirvirtuoso@gmail.com

I'd also like to thank Sharafat Ibn Mollah Mosharraf for his big support during the API design and development phase.

License

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

The PNG at the top of this README.md is from www.mockit.co.uk/about.html


Download Details:

Author: sabirvirtuoso
Source code: https://github.com/sabirvirtuoso/Mockit

License: MIT license
#swift 

Mockit: A Tasty Mocking Framework for Unit Tests in Swift 5.0
Reid  Rohan

Reid Rohan

1661792760

Module to Hook into The Node.js Require Function

require-in-the-middle

Hook into the Node.js require function. This allows you to modify modules on-the-fly as they are being required. 

Installation

npm install require-in-the-middle --save

Usage

const path = require('path')
const Hook = require('require-in-the-middle')

// Hook into the express and mongodb module
Hook(['express', 'mongodb'], function (exports, name, basedir) {
  const version = require(path.join(basedir, 'package.json')).version

  console.log('loading %s@%s', name, version)

  // expose the module version as a property on its exports object
  exports._version = version

  // whatever you return will be returned by `require`
  return exports
})

API

The require-in-the-middle module exposes a single function:

hook = Hook([modules][, options], onrequire)

When called a hook object is returned.

Arguments:

  • modules <string[]> An optional array of module names to limit which modules trigger a call of the onrequire callback. If specified, this must be the first argument. Both regular modules (e.g. react-dom) and sub-modules (e.g. react-dom/server) can be specified in the array.
  • options <Object> An optional object containing fields that change when the onrequire callback is called. If specified, this must be the second argument.
    • options.internals <boolean> Specifies whether onrequire should be called when module-internal files are loaded; defaults to false.
  • onrequire <Function> The function to call when a module is required.

The onrequire callback will be called the first time a module is required. The function is called with three arguments:

  • exports <Object> The value of the module.exports property that would normally be exposed by the required module.
  • name <string> The name of the module being required. If options.internals was set to true, the path of module-internal files that are loaded (relative to basedir) will be appended to the module name, separated by path.sep.
  • basedir <string> The directory where the module is located, or undefined for core modules.

Return the value you want the module to expose (normally the exports argument).

hook.unhook()

Removes the onrequire callback so that it will not be triggerd by subsequent calls to require().

Download Details:

Author: Elastic
Source Code: https://github.com/elastic/require-in-the-middle 
License: MIT license

#javascript #node #function 

Module to Hook into The Node.js Require Function

A Collection Of Swift Tips & Tricks That I've Shared on Twitter

⚠️ This list is no longer being updated. For my latest Swift tips, checkout the "Tips" section on Swift by Sundell.

Swift tips & tricks ⚡️

One of the things I really love about Swift is how I keep finding interesting ways to use it in various situations, and when I do - I usually share them on Twitter. Here's a collection of all the tips & tricks that I've shared so far. Each entry has a link to the original tweet, if you want to respond with some feedback or question, which is always super welcome! 🚀

Also make sure to check out all of my other Swift content:

#102 Making async tests faster and more stable

🚀 Here are some quick tips to make async tests faster & more stable:

  • 😴 Avoid sleep() - use expectations instead
  • ⏱ Use generous timeouts to avoid flakiness on CI
  • 🧐 Put all assertions at the end of each test, not inside closures
// BEFORE:

class MentionDetectorTests: XCTestCase {
    func testDetectingMention() {
        let detector = MentionDetector()
        let string = "This test was written by @johnsundell."

        detector.detectMentions(in: string) { mentions in
            XCTAssertEqual(mentions, ["johnsundell"])
        }
        
        sleep(2)
    }
}

// AFTER:

class MentionDetectorTests: XCTestCase {
    func testDetectingMention() {
        let detector = MentionDetector()
        let string = "This test was written by @johnsundell."

        var mentions: [String]?
        let expectation = self.expectation(description: #function)

        detector.detectMentions(in: string) {
            mentions = $0
            expectation.fulfill()
        }

        waitForExpectations(timeout: 10)
        XCTAssertEqual(mentions, ["johnsundell"])
    }
}

For more on async testing, check out "Unit testing asynchronous Swift code".

#101 Adding support for Apple Pencil double-taps

✍️ Adding support for the new Apple Pencil double-tap feature is super easy! All you have to do is to create a UIPencilInteraction, add it to a view, and implement one delegate method. Hopefully all pencil-compatible apps will soon adopt this.

let interaction = UIPencilInteraction()
interaction.delegate = self
view.addInteraction(interaction)

extension ViewController: UIPencilInteractionDelegate {
    func pencilInteractionDidTap(_ interaction: UIPencilInteraction) {
        // Handle pencil double-tap
    }
}

For more on using this and other iPad Pro features, check out "Building iPad Pro features in Swift".

#100 Combining values with functions

😎 Here's a cool function that combines a value with a function to return a closure that captures that value, so that it can be called without any arguments. Super useful when working with closure-based APIs and we want to use some of our properties without having to capture self.

func combine<A, B>(_ value: A, with closure: @escaping (A) -> B) -> () -> B {
    return { closure(value) }
}

// BEFORE:

class ProductViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        buyButton.handler = { [weak self] in
            guard let self = self else {
                return
            }
            
            self.productManager.startCheckout(for: self.product)
        }
    }
}

// AFTER:

class ProductViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        buyButton.handler = combine(product, with: productManager.startCheckout)
    }
}

#99 Dependency injection using functions

💉 When I'm only using a single function from a dependency, I love to inject that function as a closure, instead of having to create a protocol and inject the whole object. Makes dependency injection & testing super simple.

final class ArticleLoader {
    typealias Networking = (Endpoint) -> Future<Data>
    
    private let networking: Networking
    
    init(networking: @escaping Networking = URLSession.shared.load) {
        self.networking = networking
    }
    
    func loadLatest() -> Future<[Article]> {
        return networking(.latestArticles).decode()
    }
}

For more on this technique, check out "Simple Swift dependency injection with functions".

#98 Using a custom exception handler

💥 It's cool that you can easily assign a closure as a custom NSException handler. This is super useful when building things in Playgrounds - since you can't use breakpoints - so instead of just signal SIGABRT, you'll get the full exception description if something goes wrong.

NSSetUncaughtExceptionHandler { exception in
    print(exception)
}

#97 Using type aliases to give semantic meaning to primitives

❤️ I love that in Swift, we can use the type system to make our code so much more self-documenting - one way of doing so is to use type aliases to give the primitive types that we use a more semantic meaning.

extension List.Item {
    // Using type aliases, we can give semantic meaning to the
    // primitive types that we use, without having to introduce
    // wrapper types.
    typealias Index = Int
}

extension List {
    enum Mutation {
        // Our enum cases now become a lot more self-documenting,
        // without having to add additional parameter labels to
        // explain them.
        case add(Item, Item.Index)
        case update(Item, Item.Index)
        case remove(Item.Index)
    }
}

For more on self-documenting code, check out "Writing self-documenting Swift code".

#96 Specializing protocols using constraints

🤯 A little late night prototyping session reveals that protocol constraints can not only be applied to extensions - they can also be added to protocol definitions!

This is awesome, since it lets us easily define specialized protocols based on more generic ones.

protocol Component {
    associatedtype Container
    func add(to container: Container)
}

// Protocols that inherit from other protocols can include
// constraints to further specialize them.
protocol ViewComponent: Component where Container == UIView {
    associatedtype View: UIView
    var view: View { get }
}

extension ViewComponent {
    func add(to container: UIView) {
        container.addSubview(view)
    }
}

For more on specializing protocols, check out "Specializing protocols in Swift".

#95 Unwrapping an optional or throwing an error

📦 Here's a super handy extension on Swift's Optional type, which gives us a really nice API for easily unwrapping an optional, or throwing an error in case the value turned out to be nil:

extension Optional {
    func orThrow(_ errorExpression: @autoclosure () -> Error) throws -> Wrapped {
        switch self {
        case .some(let value):
            return value
        case .none:
            throw errorExpression()
        }
    }
}

let file = try loadFile(at: path).orThrow(MissingFileError())

For more ways that optionals can be extended, check out "Extending optionals in Swift".

#94 Testing code that uses static APIs

👩‍🔬 Testing code that uses static APIs can be really tricky, but there's a way that it can often be done - using Swift's first class function capabilities!

Instead of accessing that static API directly, we can inject the function we want to use, which enables us to mock it!

// BEFORE

class FriendsLoader {
    func loadFriends(then handler: @escaping (Result<[Friend]>) -> Void) {
        Networking.loadData(from: .friends) { result in
            ...
        }
    }
}

// AFTER

class FriendsLoader {
    typealias Handler<T> = (Result<T>) -> Void
    typealias DataLoadingFunction = (Endpoint, @escaping Handler<Data>) -> Void

    func loadFriends(using dataLoading: DataLoadingFunction = Networking.loadData,
                     then handler: @escaping Handler<[Friend]>) {
        dataLoading(.friends) { result in
            ...
        }
    }
}

// MOCKING IN TESTS

let dataLoading: FriendsLoader.DataLoadingFunction = { _, handler in
    handler(.success(mockData))
}

friendsLoader.loadFriends(using: dataLoading) { result in
    ...
}

#93 Matching multiple enum cases with associated values

🐾 Swift's pattern matching capabilities are so powerful! Two enum cases with associated values can even be matched and handled by the same switch case - which is super useful when handling state changes with similar data.

enum DownloadState {
    case inProgress(progress: Double)
    case paused(progress: Double)
    case cancelled
    case finished(Data)
}

func downloadStateDidChange(to state: DownloadState) {
    switch state {
    case .inProgress(let progress), .paused(let progress):
        updateProgressView(with: progress)
    case .cancelled:
        showCancelledMessage()
    case .finished(let data):
        process(data)
    }
}

#92 Multiline string literals

🅰 One really nice benefit of Swift multiline string literals - even for single lines of text - is that they don't require quotes to be escaped. Perfect when working with things like HTML, or creating a custom description for an object.

let html = highlighter.highlight("Array<String>")

XCTAssertEqual(html, """
<span class="type">Array</span>&lt;<span class="type">String</span>&gt;
""")

#91 Reducing sequences

💎 While it's very common in functional programming, the reduce function might be a bit of a hidden gem in Swift. It provides a super useful way to transform a sequence into a single value.

extension Sequence where Element: Equatable {
    func numberOfOccurrences(of target: Element) -> Int {
        return reduce(0) { result, element in
            guard element == target else {
                return result
            }

            return result + 1
        }
    }
}

You can read more about transforming collections in "Transforming collections in Swift".

#90 Avoiding manual Codable implementations

📦 When I use Codable in Swift, I want to avoid manual implementations as much as possible, even when there's a mismatch between my code structure and the JSON I'm decoding.

One way that can often be achieved is to use private data containers combined with computed properties.

struct User: Codable {
    let name: String
    let age: Int

    var homeTown: String { return originPlace.name }

    private let originPlace: Place
}

private extension User {
    struct Place: Codable {
        let name: String
    }
}

extension User {
    struct Container: Codable {
        let user: User
    }
}

#89 Using feature flags instead of feature branches

🚢 Instead of using feature branches, I merge almost all of my code directly into master - and then I use feature flags to conditionally enable features when they're ready. That way I can avoid merge conflicts and keep shipping!

extension ListViewController {
    func addSearchIfNeeded() {
        // Rather than having to keep maintaining a separate
        // feature branch for a new feature, we can use a flag
        // to conditionally turn it on.
        guard FeatureFlags.searchEnabled else {
            return
        }

        let resultsVC = SearchResultsViewController()
        let searchVC = UISearchController(
            searchResultsController: resultsVC
        )

        searchVC.searchResultsUpdater = resultsVC
        navigationItem.searchController = searchVC
    }
}

You can read more about feature flags in "Feature flags in Swift".

#88 Lightweight data hierarchies using tuples

💾 Here I'm using tuples to create a lightweight hierarchy for my data, giving me a nice structure without having to introduce any additional types.

struct CodeSegment {
    var tokens: (
        previous: String?,
        current: String
    )

    var delimiters: (
        previous: Character?
        next: Character?
    )
}

handle(segment.tokens.current)

You can read more about tuples in "Using tuples as lightweight types in Swift"

#87 The rule of threes

3️⃣ Whenever I have 3 properties or local variables that share the same prefix, I usually try to extract them into their own method or type. That way I can avoid massive types & methods, and also increase readability, without falling into a "premature optimization" trap.

Before

public func generate() throws {
    let contentFolder = try folder.subfolder(named: "content")

    let articleFolder = try contentFolder.subfolder(named: "posts")
    let articleProcessor = ContentProcessor(folder: articleFolder)
    let articles = try articleProcessor.process()

    ...
}

After

public func generate() throws {
    let contentFolder = try folder.subfolder(named: "content")
    let articles = try processArticles(in: contentFolder)
    ...
}

private func processArticles(in folder: Folder) throws -> [ContentItem] {
    let folder = try folder.subfolder(named: "posts")
    let processor = ContentProcessor(folder: folder)
    return try processor.process()
}

#86 Useful Codable extensions

👨‍🔧 Here's two extensions that I always add to the Encodable & Decodable protocols, which for me really make the Codable API nicer to use. By using type inference for decoding, a lot of boilerplate can be removed when the compiler is already able to infer the resulting type.

extension Encodable {
    func encoded() throws -> Data {
        return try JSONEncoder().encode(self)
    }
}

extension Data {
    func decoded<T: Decodable>() throws -> T {
        return try JSONDecoder().decode(T.self, from: self)
    }
}

let data = try user.encoded()

// By using a generic type in the decoded() method, the
// compiler can often infer the type we want to decode
// from the current context.
try userDidLogin(data.decoded())

// And if not, we can always supply the type, still making
// the call site read very nicely.
let otherUser = try data.decoded() as User

#85 Using shared UserDefaults suites

📦 UserDefaults is a lot more powerful than what it first might seem like. Not only can it store more complex values (like dates & dictionaries) and parse command line arguments - it also enables easy sharing of settings & lightweight data between apps in the same App Group.

let sharedDefaults = UserDefaults(suiteName: "my-app-group")!
let useDarkMode = sharedDefaults.bool(forKey: "dark-mode")

// This value is put into the shared suite.
sharedDefaults.set(true, forKey: "dark-mode")

// If you want to treat the shared settings as read-only (and add
// local overrides on top of them), you can simply add the shared
// suite to the standard UserDefaults.
let combinedDefaults = UserDefaults.standard
combinedDefaults.addSuite(named: "my-app-group")

// This value is a local override, not added to the shared suite.
combinedDefaults.set(true, forKey: "app-specific-override")

#84 Custom UIView backing layers

🎨 By overriding layerClass you can tell UIKit what CALayer class to use for a UIView's backing layer. That way you can reduce the amount of layers, and don't have to do any manual layout.

final class GradientView: UIView {
    override class var layerClass: AnyClass { return CAGradientLayer.self }

    var colors: (start: UIColor, end: UIColor)? {
        didSet { updateLayer() }
    }

    private func updateLayer() {
        let layer = self.layer as! CAGradientLayer
        layer.colors = colors.map { [$0.start.cgColor, $0.end.cgColor] }
    }
}

#83 Auto-Equatable enums with associated values

✅ That the compiler now automatically synthesizes Equatable conformances is such a huge upgrade for Swift! And the cool thing is that it works for all kinds of types - even for enums with associated values! Especially useful when using enums for verification in unit tests.

struct Article: Equatable {
    let title: String
    let text: String
}

struct User: Equatable {
    let name: String
    let age: Int
}

extension Navigator {
    enum Destination: Equatable {
        case profile(User)
        case article(Article)
    }
}

func testNavigatingToArticle() {
    let article = Article(title: "Title", text: "Text")
    controller.select(article)
    XCTAssertEqual(navigator.destinations, [.article(article)])
}

#82 Defaults for associated types

🤝 Associated types can have defaults in Swift - which is super useful for types that are not easily inferred (for example when they're not used for a specific instance method or property).

protocol Identifiable {
    associatedtype RawIdentifier: Codable = String

    var id: Identifier<Self> { get }
}

struct User: Identifiable {
    let id: Identifier<User>
    let name: String
}

struct Group: Identifiable {
    typealias RawIdentifier = Int

    let id: Identifier<Group>
    let name: String
}

#81 Creating a dedicated identifier type

🆔 If you want to avoid using plain strings as identifiers (which can increase both type safety & readability), it's really easy to create a custom Identifier type that feels just like a native Swift type, thanks to protocols!

More on this topic in "Type-safe identifiers in Swift".

struct Identifier: Hashable {
    let string: String
}

extension Identifier: ExpressibleByStringLiteral {
    init(stringLiteral value: String) {
        string = value
    }
}

extension Identifier: CustomStringConvertible {
    var description: String {
        return string
    }
}

extension Identifier: Codable {
    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        string = try container.decode(String.self)
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        try container.encode(string)
    }
}

struct Article: Codable {
    let id: Identifier
    let title: String
}

let article = Article(id: "my-article", title: "Hello world!")

#80 Assigning optional tuple members to variables

🙌 A really cool thing about using tuples to model the internal state of a Swift type, is that you can unwrap an optional tuple's members directly into local variables.

Very useful in order to group multiple optional values together for easy unwrapping & handling.

class ImageTransformer {
    private var queue = [(image: UIImage, transform: Transform)]()

    private func processNext() {
        // When unwrapping an optional tuple, you can assign the members
        // directly to local variables.
        guard let (image, transform) = queue.first else {
            return
        }

        let context = Context()
        context.draw(image)
        context.apply(transform)
        ...
    }
}

#79 Struct convenience initializers

❤️ I love to structure my code using extensions in Swift. One big benefit of doing so when it comes to struct initializers, is that defining a convenience initializer doesn't remove the default one the compiler generates - best of both worlds!

struct Article {
    let date: Date
    var title: String
    var text: String
    var comments: [Comment]
}

extension Article {
    init(title: String, text: String) {
        self.init(date: Date(), title: title, text: text, comments: [])
    }
}

let articleA = Article(title: "Best Cupcake Recipe", text: "...")

let articleB = Article(
    date: Date(),
    title: "Best Cupcake Recipe",
    text: "...",
    comments: [
        Comment(user: currentUser, text: "Yep, can confirm!")
    ]
)

#78 Usages of throwing functions

🏈 A big benefit of using throwing functions for synchronous Swift APIs is that the caller can decide whether they want to treat the return value as optional (try?) or required (try).

func loadFile(named name: String) throws -> File {
    guard let url = urlForFile(named: name) else {
        throw File.Error.missing
    }

    do {
        let data = try Data(contentsOf: url)
        return File(url: url, data: data)
    } catch {
        throw File.Error.invalidData(error)
    }
}

let requiredFile = try loadFile(named: "AppConfig.json")

let optionalFile = try? loadFile(named: "UserSettings.json")

#77 Nested generic types

🐝 Types that are nested in generics automatically inherit their parent's generic types - which is super useful when defining accessory types (for things like states or outcomes).

struct Task<Input, Output> {
    typealias Closure = (Input) throws -> Output

    let closure: Closure
}

extension Task {
    enum Result {
        case success(Output)
        case failure(Error)
    }
}

#76 Equatable & Hashable structures

🤖 Now that the Swift compiler automatically synthesizes Equatable & Hashable conformances for value types, it's easier than ever to setup model structures with nested types that are all Equatable/Hashable!

typealias Value = Hashable & Codable

struct User: Value {
    var name: String
    var age: Int
    var lastLoginDate: Date?
    var settings: Settings
}

extension User {
    struct Settings: Value {
        var itemsPerPage: Int
        var theme: Theme
    }
}

extension User.Settings {
    enum Theme: String, Value {
        case light
        case dark
    }
}

You can read more about using nested types in Swift here.

#75 Conditional conformances

🎉 Swift 4.1 is here! One of the key features it brings is conditional conformances, which lets you have a type only conform to a protocol under certain constraints.

protocol UnboxTransformable {
    associatedtype RawValue

    static func transform(_ value: RawValue) throws -> Self?
}

extension Array: UnboxTransformable where Element: UnboxTransformable {
    typealias RawValue = [Element.RawValue]

    static func transform(_ value: RawValue) throws -> [Element]? {
        return try value.compactMap(Element.transform)
    }
}

I also have an article with lots of more info on conditional conformances here. Paul Hudson also has a great overview of all Swift 4.1 features here.

#74 Generic type aliases

🕵️‍♀️ A cool thing about Swift type aliases is that they can be generic! Combine that with tuples and you can easily define simple generic types.

typealias Pair<T> = (T, T)

extension Game {
    func calculateScore(for players: Pair<Player>) -> Int {
        ...
    }
}

You can read more about using tuples as lightweight types here.

#73 Parsing command line arguments using UserDefaults

☑️ A really cool "hidden" feature of UserDefaults is that it contains any arguments that were passed to the app at launch!

Super useful both in Swift command line tools & scripts, but also to temporarily override a value when debugging iOS apps.

let defaults = UserDefaults.standard
let query = defaults.string(forKey: "query")
let resultCount = defaults.integer(forKey: "results")

#72 Using the & operator

👏 Swift's & operator is awesome! Not only can you use it to compose protocols, you can compose other types too! Very useful if you want to hide concrete types & implementation details.

protocol LoadableFromURL {
    func load(from url: URL)
}

class ContentViewController: UIViewController, LoadableFromURL {
    func load(from url: URL) {
        ...
    }
}

class ViewControllerFactory {
    func makeContentViewController() -> UIViewController & LoadableFromURL {
        return ContentViewController()
    }
}

#71 Capturing multiple values in mocks

🤗 When capturing values in mocks, using an array (instead of just a single value) makes it easy to verify that only a certain number of values were passed.

Perfect for protecting against "over-calling" something.

class UserManagerTests: XCTestCase {
    func testObserversCalledWhenUserFirstLogsIn() {
        let manager = UserManager()

        let observer = ObserverMock()
        manager.addObserver(observer)

        // First login, observers should be notified
        let user = User(id: 123, name: "John")
        manager.userDidLogin(user)
        XCTAssertEqual(observer.users, [user])

        // If the same user logs in again, observers shouldn't be notified
        manager.userDidLogin(user)
        XCTAssertEqual(observer.users, [user])
    }
}

private extension UserManagerTests {
    class ObserverMock: UserManagerObserver {
        private(set) var users = [User]()

        func userDidChange(to user: User) {
            users.append(user)
        }
    }
}

#70 Reducing the need for mocks

👋 When writing tests, you don't always need to create mocks - you can create stubs using real instances of things like errors, URLs & UserDefaults.

Here's how to do that for some common tasks/object types in Swift:

// Create errors using NSError (#function can be used to reference the name of the test)
let error = NSError(domain: #function, code: 1, userInfo: nil)

// Create non-optional URLs using file paths
let url = URL(fileURLWithPath: "Some/URL")

// Reference the test bundle using Bundle(for:)
let bundle = Bundle(for: type(of: self))

// Create an explicit UserDefaults object (instead of having to use a mock)
let userDefaults = UserDefaults(suiteName: #function)

// Create queues to control/await concurrent operations
let queue = DispatchQueue(label: #function)

For when you actually do need mocking, check out "Mocking in Swift".

#69 Using "then" as an external parameter label for closures

⏱ I've started using "then" as an external parameter label for completion handlers. Makes the call site read really nicely (Because I do ❤️ conversational API design) regardless of whether trailing closure syntax is used or not.

protocol DataLoader {
    // Adding type aliases to protocols can be a great way to
    // reduce verbosity for parameter types.
    typealias Handler = (Result<Data>) -> Void
    associatedtype Endpoint

    func loadData(from endpoint: Endpoint, then handler: @escaping Handler)
}

loader.loadData(from: .messages) { result in
    ...
}

loader.loadData(from: .messages, then: { result in
    ...
})

#68 Combining lazily evaluated sequences with the builder pattern

😴 Combining lazily evaluated sequences with builder pattern-like properties can lead to some pretty sweet APIs for configurable sequences in Swift.

Also useful for queries & other things you "build up" and then execute.

// Extension adding builder pattern-like properties that return
// a new sequence value with the given configuration applied
extension FileSequence {
    var recursive: FileSequence {
        var sequence = self
        sequence.isRecursive = true
        return sequence
    }

    var includingHidden: FileSequence {
        var sequence = self
        sequence.includeHidden = true
        return sequence
    }
}

// BEFORE

let files = folder.makeFileSequence(recursive: true, includeHidden: true)

// AFTER

let files = folder.files.recursive.includingHidden

Want an intro to lazy sequences? Check out "Swift sequences: The art of being lazy".

#67 Faster & more stable UI tests

My top 3 tips for faster & more stable UI tests:

📱 Reset the app's state at the beginning of every test.

🆔 Use accessibility identifiers instead of UI strings.

⏱ Use expectations instead of waiting time.

func testOpeningArticle() {
    // Launch the app with an argument that tells it to reset its state
    let app = XCUIApplication()
    app.launchArguments.append("--uitesting")
    app.launch()
    
    // Check that the app is displaying an activity indicator
    let activityIndicator = app.activityIndicator.element
    XCTAssertTrue(activityIndicator.exists)
    
    // Wait for the loading indicator to disappear = content is ready
    expectation(for: NSPredicate(format: "exists == 0"),
                evaluatedWith: activityIndicator)
                
    // Use a generous timeout in case the network is slow
    waitForExpectations(timeout: 10)
    
    // Tap the cell for the first article
    app.tables.cells["Article.0"].tap()
    
    // Assert that a label with the accessibility identifier "Article.Title" exists
    let label = app.staticTexts["Article.Title"]
    XCTAssertTrue(label.exists)
}

#66 Accessing the clipboard from a Swift script

📋 It's super easy to access the contents of the clipboard from a Swift script. A big benefit of Swift scripting is being able to use Cocoa's powerful APIs for Mac apps.

import Cocoa

let clipboard = NSPasteboard.general.string(forType: .string)

#65 Using tuples for view state

🎯 Using Swift tuples for view state can be a super nice way to group multiple properties together and render them reactively using the layout system.

By using a tuple we don't have to either introduce a new type or make our view model-aware.

class TextView: UIView {
    var state: (title: String?, text: String?) {
        // By telling UIKit that our view needs layout and binding our
        // state in layoutSubviews, we can react to state changes without
        // doing unnecessary layout work.
        didSet { setNeedsLayout() }
    }

    private let titleLabel = UILabel()
    private let textLabel = UILabel()

    override func layoutSubviews() {
        super.layoutSubviews()

        titleLabel.text = state.title
        textLabel.text = state.text

        ...
    }
}

#64 Throwing tests and LocalizedError

⚾️ Swift tests can throw, which is super useful in order to avoid complicated logic or force unwrapping. By making errors conform to LocalizedError, you can also get a nice error message in Xcode if there's a failure.

class ImageCacheTests: XCTestCase {
    func testCachingAndLoadingImage() throws {
        let bundle = Bundle(for: type(of: self))
        let cache = ImageCache(bundle: bundle)
        
        // Bonus tip: You can easily load images from your test
        // bundle using this UIImage initializer
        let image = try require(UIImage(named: "sample", in: bundle, compatibleWith: nil))
        try cache.cache(image, forKey: "key")
        
        let cachedImage = try cache.image(forKey: "key")
        XCTAssertEqual(image, cachedImage)
    }
}

enum ImageCacheError {
    case emptyKey
    case dataConversionFailed
}

// When using throwing tests, making your errors conform to
// LocalizedError will render a much nicer error message in
// Xcode (per default only the error code is shown).
extension ImageCacheError: LocalizedError {
    var errorDescription: String? {
        switch self {
        case .emptyKey:
            return "An empty key was given"
        case .dataConversionFailed:
            return "Failed to convert the given image to Data"
        }
    }
}

For more information, and the implementation of the require method used above, check out "Avoiding force unwrapping in Swift unit tests".

#63 The difference between static and class properties

✍️ Unlike static properties, class properties can be overridden by subclasses (however, they can't be stored, only computed).

class TableViewCell: UITableViewCell {
    class var preferredHeight: CGFloat { return 60 }
}

class TallTableViewCell: TableViewCell {
    override class var preferredHeight: CGFloat { return 100 }
}

#62 Creating extensions with static factory methods

👨‍🎨 Creating extensions with static factory methods can be a great alternative to subclassing in Swift, especially for things like setting up UIViews, CALayers or other kinds of styling.

It also lets you remove a lot of styling & setup from your view controllers.

extension UILabel {
    static func makeForTitle() -> UILabel {
        let label = UILabel()
        label.font = .boldSystemFont(ofSize: 24)
        label.textColor = .darkGray
        label.adjustsFontSizeToFitWidth = true
        label.minimumScaleFactor = 0.75
        return label
    }

    static func makeForText() -> UILabel {
        let label = UILabel()
        label.font = .systemFont(ofSize: 16)
        label.textColor = .black
        label.numberOfLines = 0
        return label
    }
}

class ArticleViewController: UIViewController {
    lazy var titleLabel = UILabel.makeForTitle()
    lazy var textLabel = UILabel.makeForText()
}

#61 Child view controller auto-resizing

🧒 An awesome thing about child view controllers is that they're automatically resized to match their parent, making them a super nice solution for things like loading & error views.

class ListViewController: UIViewController {
    func loadItems() {
        let loadingViewController = LoadingViewController()
        add(loadingViewController)

        dataLoader.loadItems { [weak self] result in
            loadingViewController.remove()
            self?.handle(result)
        }
    }
}

For more about child view controller (including the add and remove methods used above), check out "Using child view controllers as plugins in Swift".

#60 Using zip

🤐 Using the zip function in Swift you can easily combine two sequences. Super useful when using two sequences to do some work, since zip takes care of all the bounds-checking.

func render(titles: [String]) {
    for (label, text) in zip(titleLabels, titles) {
        print(text)
        label.text = text
    }
}

#59 Defining custom option sets

🎛 The awesome thing about option sets in Swift is that they can automatically either be passed as a single member or as a set. Even cooler is that you can easily define your own option sets as well, perfect for options and other non-exclusive values.

// Option sets are awesome, because you can easily pass them
// both using dot syntax and array literal syntax, like when
// using the UIView animation API:
UIView.animate(withDuration: 0.3,
               delay: 0,
               options: .allowUserInteraction,
               animations: animations)

UIView.animate(withDuration: 0.3,
               delay: 0,
               options: [.allowUserInteraction, .layoutSubviews],
               animations: animations)

// The cool thing is that you can easily define your own option
// sets as well, by defining a struct that has an Int rawValue,
// that will be used as a bit mask.
extension Cache {
    struct Options: OptionSet {
        static let saveToDisk = Options(rawValue: 1)
        static let clearOnMemoryWarning = Options(rawValue: 1 << 1)
        static let clearDaily = Options(rawValue: 1 << 2)

        let rawValue: Int
    }
}

// We can now use Cache.Options just like UIViewAnimationOptions:
Cache(options: .saveToDisk)
Cache(options: [.saveToDisk, .clearDaily])

#58 Using the where clause with associated types

🙌 Using the where clause when designing protocol-oriented APIs in Swift can let your implementations (or others' if it's open source) have a lot more freedom, especially when it comes to collections.

See "Using generic type constraints in Swift 4" for more info.

public protocol PathFinderMap {
    associatedtype Node
    // Using the 'where' clause for associated types, we can
    // ensure that a type meets certain requirements (in this
    // case that it's a sequence with Node elements).
    associatedtype NodeSequence: Sequence where NodeSequence.Element == Node

    // Instead of using a concrete type (like [Node]) here, we
    // give implementors of this protocol more freedom while
    // still meeting our requirements. For example, one
    // implementation might use Set<Node>.
    func neighbors(of node: Node) -> NodeSequence
}

#57 Using first class functions when iterating over a dictionary

👨‍🍳 Combine first class functions in Swift with the fact that Dictionary elements are (Key, Value) tuples and you can build yourself some pretty awesome functional chains when iterating over a Dictionary.

func makeActor(at coordinate: Coordinate, for building: Building) -> Actor {
    let actor = Actor()
    actor.position = coordinate.point
    actor.animation = building.animation
    return actor
}

func render(_ buildings: [Coordinate : Building]) {
    buildings.map(makeActor).forEach(add)
}

#56 Calling instance methods as static functions

😎 In Swift, you can call any instance method as a static function and it will return a closure representing that method. This is how running tests using SPM on Linux works.

More about this topic in my blog post "First class functions in Swift".

// This produces a '() -> Void' closure which is a reference to the
// given view's 'removeFromSuperview' method.
let closure = UIView.removeFromSuperview(view)

// We can now call it just like we would any other closure, and it
// will run 'view.removeFromSuperview()'
closure()

// This is how running tests using the Swift Package Manager on Linux
// works, you return your test functions as closures:
extension UserManagerTests {
    static var allTests = [
        ("testLoggingIn", testLoggingIn),
        ("testLoggingOut", testLoggingOut),
        ("testUserPermissions", testUserPermissions)
    ]
}

#55 Dropping suffixes from method names to support multiple arguments

👏 One really nice benefit of dropping suffixes from method names (and just using verbs, when possible) is that it becomes super easy to support both single and multiple arguments, and it works really well semantically.

extension UIView {
    func add(_ subviews: UIView...) {
        subviews.forEach(addSubview)
    }
}

view.add(button)
view.add(label)

// By dropping the "Subview" suffix from the method name, both
// single and multiple arguments work really well semantically.
view.add(button, label)

#54 Constraining protocols to classes to ensure mutability

👽 Using the AnyObject (or class) constraint on protocols is not only useful when defining delegates (or other weak references), but also when you always want instances to be mutable without copying.

// By constraining a protocol with 'AnyObject' it can only be adopted
// by classes, which means all instances will always be mutable, and
// that it's the original instance (not a copy) that will be mutated.
protocol DataContainer: AnyObject {
    var data: Data? { get set }
}

class UserSettingsManager {
    private var settings: Settings
    private let dataContainer: DataContainer

    // Since DataContainer is a protocol, we an easily mock it in
    // tests if we use dependency injection
    init(settings: Settings, dataContainer: DataContainer) {
        self.settings = settings
        self.dataContainer = dataContainer
    }

    func saveSettings() throws {
        let data = try settings.serialize()

        // We can now assign properties on an instance of our protocol
        // because the compiler knows it's always going to be a class
        dataContainer.data = data
    }
}

#53 String-based enums in string interpolation

🍣 Even if you define a custom raw value for a string-based enum in Swift, the full case name will be used in string interpolation.

Super useful when using separate raw values for JSON, while still wanting to use the full case name in other contexts.

extension Building {
    // This enum has custom raw values that are used when decoding
    // a value, for example from JSON.
    enum Kind: String {
        case castle = "C"
        case town = "T"
        case barracks = "B"
        case goldMine = "G"
        case camp = "CA"
        case blacksmith = "BL"
    }

    var animation: Animation {
        return Animation(
            // When used in string interpolation, the full case name is still used.
            // For 'castle' this will be 'buildings/castle'.
            name: "buildings/\(kind)",
            frameCount: frameCount,
            frameDuration: frameDuration
        )
    }
}

#52 Expressively comparing a value with a list of candidates

👨‍🔬 Continuing to experiment with expressive ways of comparing a value with a list of candidates in Swift. Adding an extension on Equatable is probably my favorite approach so far.

extension Equatable {
    func isAny(of candidates: Self...) -> Bool {
        return candidates.contains(self)
    }
}

let isHorizontal = direction.isAny(of: .left, .right)

See tip #35 for my previous experiment.

#51 UIView bounds and transforms

📐 A really interesting side-effect of a UIView's bounds being its rect within its own coordinate system is that transforms don't affect it at all. That's why it's usually a better fit than frame when doing layout calculations of subviews.

let view = UIView()
view.frame.size = CGSize(width: 100, height: 100)
view.transform = CGAffineTransform(scaleX: 2, y: 2)

print(view.frame) // (-50.0, -50.0, 200.0, 200.0)
print(view.bounds) // (0.0, 0.0, 100.0, 100.0)

#50 UIKit default arguments

👏 It's awesome that many UIKit APIs with completion handlers and other optional parameters import into Swift with default arguments (even though they are written in Objective-C). Getting rid of all those nil arguments is so nice!

// BEFORE: All parameters are specified, just like in Objective-C

viewController.present(modalViewController, animated: true, completion: nil)

modalViewController.dismiss(animated: true, completion: nil)

viewController.transition(from: loadingViewController,
                          to: contentViewController,
                          duration: 0.3,
                          options: [],
                          animations: animations,
                          completion: nil)

// AFTER: Since many UIKit APIs with completion handlers and other
// optional parameters import into Swift with default arguments,
// we can make our calls shorter

viewController.present(modalViewController, animated: true)

modalViewController.dismiss(animated: true)

viewController.transition(from: loadingViewController,
                          to: contentViewController,
                          duration: 0.3,
                          animations: animations)

#49 Avoiding Massive View Controllers

✂️ Avoiding Massive View Controllers is all about finding the right levels of abstraction and splitting things up.

My personal rule of thumb is that as soon as I have 3 methods or properties that have the same prefix, I break them out into their own type.

// BEFORE

class LoginViewController: UIViewController {
    private lazy var signUpLabel = UILabel()
    private lazy var signUpImageView = UIImageView()
    private lazy var signUpButton = UIButton()
}

// AFTER

class LoginViewController: UIViewController {
    private lazy var signUpView = SignUpView()
}

class SignUpView: UIView {
    private lazy var label = UILabel()
    private lazy var imageView = UIImageView()
    private lazy var button = UIButton()
}

#48 Extending optionals

❤️ I love the fact that optionals are enums in Swift - it makes it so easy to extend them with convenience APIs for certain types. Especially useful when doing things like data validation on optional values.

func validateTextFields() -> Bool {
    guard !usernameTextField.text.isNilOrEmpty else {
        return false
    }

    ...

    return true
}

// Since all optionals are actual enum values in Swift, we can easily
// extend them for certain types, to add our own convenience APIs

extension Optional where Wrapped == String {
    var isNilOrEmpty: Bool {
        switch self {
        case let string?:
            return string.isEmpty
        case nil:
            return true
        }
    }
}

// Since strings are now Collections in Swift 4, you can even
// add this property to all optional collections:

extension Optional where Wrapped: Collection {
    var isNilOrEmpty: Bool {
        switch self {
        case let collection?:
            return collection.isEmpty
        case nil:
            return true
        }
    }
}

#47 Using where with for-loops

🗺 Using the where keyword can be a super nice way to quickly apply a filter in a for-loop in Swift. You can of course use map, filter and forEach, or guard, but for simple loops I think this is very expressive and nice.

func archiveMarkedPosts() {
    for post in posts where post.isMarked {
        archive(post)
    }
}

func healAllies() {
    for player in players where player.isAllied(to: currentPlayer) {
        player.heal()
    }
}

#46 Variable shadowing

👻 Variable shadowing can be super useful in Swift, especially when you want to create a local copy of a parameter value in order to use it as state within a closure.

init(repeatMode: RepeatMode, closure: @escaping () -> UpdateOutcome) {
    // Shadow the argument with a local, mutable copy
    var repeatMode = repeatMode
    
    self.closure = {
        // With shadowing, there's no risk of accidentially
        // referring to the immutable version
        switch repeatMode {
        case .forever:
            break
        case .times(let count):
            guard count > 0 else {
                return .finished
            }
            
            // We can now capture the mutable version and use
            // it for state in a closure
            repeatMode = .times(count - 1)
        }
        
        return closure()
    }
}

#45 Using dot syntax for static properties and initializers

✒️ Dot syntax is one of my favorite features of Swift. What's really cool is that it's not only for enums, any static method or property can be used with dot syntax - even initializers! Perfect for convenience APIs and default parameters.

public enum RepeatMode {
    case times(Int)
    case forever
}

public extension RepeatMode {
    static var never: RepeatMode {
        return .times(0)
    }

    static var once: RepeatMode {
        return .times(1)
    }
}

view.perform(animation, repeated: .once)

// To make default parameters more compact, you can even use init with dot syntax

class ImageLoader {
    init(cache: Cache = .init(), decoder: ImageDecoder = .init()) {
        ...
    }
}

#44 Calling functions as closures with a tuple as parameters

🚀 One really cool aspect of Swift having first class functions is that you can pass any function (or even initializer) as a closure, and even call it with a tuple containing its parameters!

// This function lets us treat any "normal" function or method as
// a closure and run it with a tuple that contains its parameters
func call<Input, Output>(_ function: (Input) -> Output, with input: Input) -> Output {
    return function(input)
}

class ViewFactory {
    func makeHeaderView() -> HeaderView {
        // We can now pass an initializer as a closure, and a tuple
        // containing its parameters
        return call(HeaderView.init, with: loadTextStyles())
    }
    
    private func loadTextStyles() -> (font: UIFont, color: UIColor) {
        return (theme.font, theme.textColor)
    }
}

class HeaderView {
    init(font: UIFont, textColor: UIColor) {
        ...
    }
}

#43 Enabling static dependency injection

💉 If you've been struggling to test code that uses static APIs, here's a technique you can use to enable static dependency injection without having to modify any call sites:

// Before: Almost impossible to test due to the use of singletons

class Analytics {
    static func log(_ event: Event) {
        Database.shared.save(event)
        
        let dictionary = event.serialize()
        NetworkManager.shared.post(dictionary, to: eventURL)
    }
}

// After: Much easier to test, since we can inject mocks as arguments

class Analytics {
    static func log(_ event: Event,
                    database: Database = .shared,
                    networkManager: NetworkManager = .shared) {
        database.save(event)
        
        let dictionary = event.serialize()
        networkManager.post(dictionary, to: eventURL)
    }
}

#42 Type inference for lazy properties in Swift 4

🎉 In Swift 4, type inference works for lazy properties and you don't need to explicitly refer to self!

// Swift 3

class PurchaseView: UIView {
    private lazy var buyButton: UIButton = self.makeBuyButton()
    
    private func makeBuyButton() -> UIButton {
        let button = UIButton()
        button.setTitle("Buy", for: .normal)
        button.setTitleColor(.blue, for: .normal)
        return button
    }
}

// Swift 4

class PurchaseView: UIView {
    private lazy var buyButton = makeBuyButton()
    
    private func makeBuyButton() -> UIButton {
        let button = UIButton()
        button.setTitle("Buy", for: .normal)
        button.setTitleColor(.blue, for: .normal)
        return button
    }
}

#41 Converting Swift errors to NSError

😎 You can turn any Swift Error into an NSError, which is super useful when pattern matching with a code 👍. Also, switching on optionals is pretty cool!

let task = urlSession.dataTask(with: url) { data, _, error in
    switch error {
    case .some(let error as NSError) where error.code == NSURLErrorNotConnectedToInternet:
        presenter.showOfflineView()
    case .some(let error):
        presenter.showGenericErrorView()
    case .none:
        presenter.renderContent(from: data)
    }
}

task.resume()

Also make sure to check out Kostas Kremizas' tip about how you can pattern match directly against a member of URLError.

#40 Making UIImage macOS compatible

🖥 Here's an easy way to make iOS model code that uses UIImage macOS compatible - like me and Gui Rambo discussed on the Swift by Sundell Podcast.

// Either put this in a separate file that you only include in your macOS target or wrap the code in #if os(macOS) / #endif

import Cocoa

// Step 1: Typealias UIImage to NSImage
typealias UIImage = NSImage

// Step 2: You might want to add these APIs that UIImage has but NSImage doesn't.
extension NSImage {
    var cgImage: CGImage? {
        var proposedRect = CGRect(origin: .zero, size: size)

        return cgImage(forProposedRect: &proposedRect,
                       context: nil,
                       hints: nil)
    }

    convenience init?(named name: String) {
        self.init(named: Name(name))
    }
}

// Step 3: Profit - you can now make your model code that uses UIImage cross-platform!
struct User {
    let name: String
    let profileImage: UIImage
}

#39 Internally mutable protocol-oriented APIs

🤖 You can easily define a protocol-oriented API that can only be mutated internally, by using an internal protocol that extends a public one.

// Declare a public protocol that acts as your immutable API
public protocol ModelHolder {
    associatedtype Model
    var model: Model { get }
}

// Declare an extended, internal protocol that provides a mutable API
internal protocol MutableModelHolder: ModelHolder {
    var model: Model { get set }
}

// You can now implement the requirements using 'public internal(set)'
public class UserHolder: MutableModelHolder {
    public internal(set) var model: User

    internal init(model: User) {
        self.model = model
    }
}

#38 Switching on a set

🎛 You can switch on a set using array literals as cases in Swift! Can be really useful to avoid many if/else if statements.

class RoadTile: Tile {
    var connectedDirections = Set<Direction>()

    func render() {
        switch connectedDirections {
        case [.up, .down]:
            image = UIImage(named: "road-vertical")
        case [.left, .right]:
            image = UIImage(named: "road-horizontal")
        default:
            image = UIImage(named: "road")
        }
    }
}

#37 Adding the current locale to cache keys

🌍 When caching localized content in an app, it's a good idea to add the current locale to all keys, to prevent bugs when switching languages.

func cache(_ content: Content, forKey key: String) throws {
    let data = try wrap(content) as Data
    let key = localize(key: key)
    try storage.store(data, forKey: key)
}

func loadCachedContent(forKey key: String) -> Content? {
    let key = localize(key: key)
    let data = storage.loadData(forKey: key)
    return data.flatMap { try? unbox(data: $0) }
}

private func localize(key: String) -> String {
    return key + "-" + Bundle.main.preferredLocalizations[0]
}

#36 Setting up tests to avoid retain cycles with weak references

🚳 Here's an easy way to setup a test to avoid accidental retain cycles with object relationships (like weak delegates & observers) in Swift:

func testDelegateNotRetained() {
    // Assign the delegate (weak) and also retain it using a local var
    var delegate: Delegate? = DelegateMock()
    controller.delegate = delegate
    XCTAssertNotNil(controller.delegate)
    
    // Release the local var, which should also release the weak reference
    delegate = nil
    XCTAssertNil(controller.delegate)
}

#35 Expressively matching a value against a list of candidates

👨‍🔬 Playing around with an expressive way to check if a value matches any of a list of candidates in Swift:

// Instead of multiple conditions like this:

if string == "One" || string == "Two" || string == "Three" {

}

// You can now do:

if string == any(of: "One", "Two", "Three") {

}

You can find a gist with the implementation here.

#34 Organizing code using extensions

👪 APIs in a Swift extension automatically inherit its access control level, making it a neat way to organize public, internal & private APIs.

public extension Animation {
    init(textureNamed textureName: String) {
        frames = [Texture(name: textureName)]
    }
    
    init(texturesNamed textureNames: [String], frameDuration: TimeInterval = 1) {
        frames = textureNames.map(Texture.init)
        self.frameDuration = frameDuration
    }
    
    init(image: Image) {
        frames = [Texture(image: image)]
    }
}

internal extension Animation {
    func loadFrameImages() -> [Image] {
        return frames.map { $0.loadImageIfNeeded() }
    }
}

#33 Using map to transform an optional into a Result type

🗺 Using map you can transform an optional value into an optional Result type by simply passing in the enum case.

enum Result<Value> {
    case value(Value)
    case error(Error)
}

class Promise<Value> {
    private var result: Result<Value>?
    
    init(value: Value? = nil) {
        result = value.map(Result.value)
    }
}

#32 Assigning to self in struct initializers

👌 It's so nice that you can assign directly to self in struct initializers in Swift. Very useful when adding conformance to protocols.

extension Bool: AnswerConvertible {
    public init(input: String) throws {
        switch input.lowercased() {
        case "y", "yes", "👍":
            self = true
        default:
            self = false
        }
    }
}

#31 Recursively calling closures as inline functions

☎️ Defining Swift closures as inline functions enables you to recursively call them, which is super useful in things like custom sequences.

class Database {
    func records(matching query: Query) -> AnySequence<Record> {
        var recordIterator = loadRecords().makeIterator()
        
        func iterate() -> Record? {
            guard let nextRecord = recordIterator.next() else {
                return nil
            }
            
            guard nextRecord.matches(query) else {
                // Since the closure is an inline function, it can be recursively called,
                // in this case in order to advance to the next item.
                return iterate()
            }
            
            return nextRecord
        }
        
        // AnySequence/AnyIterator are part of the standard library and provide an easy way
        // to define custom sequences using closures.
        return AnySequence { AnyIterator(iterate) }
    }
}

Rob Napier points out that using the above might cause crashes if used on a large databaset, since Swift has no guaranteed Tail Call Optimization (TCO).

Slava Pestov also points out that another benefit of inline functions vs closures is that they can have their own generic parameter list.

#30 Passing self to required Objective-C dependencies

🏖 Using lazy properties in Swift, you can pass self to required Objective-C dependencies without having to use force-unwrapped optionals.

class DataLoader: NSObject {
    lazy var urlSession: URLSession = self.makeURLSession()
    
    private func makeURLSession() -> URLSession {
        return URLSession(configuration: .default, delegate: self, delegateQueue: .main)
    }
}

class Renderer {
    lazy var displayLink: CADisplayLink = self.makeDisplayLink()
    
    private func makeDisplayLink() -> CADisplayLink {
        return CADisplayLink(target: self, selector: #selector(screenDidRefresh))
    }
}

#29 Making weak or lazy properties readonly

👓 If you have a property in Swift that needs to be weak or lazy, you can still make it readonly by using private(set).

class Node {
    private(set) weak var parent: Node?
    private(set) lazy var children = [Node]()

    func add(child: Node) {
        children.append(child)
        child.parent = self
    }
}

#28 Defining static URLs using string literals

🌏 Tired of using URL(string: "url")! for static URLs? Make URL conform to ExpressibleByStringLiteral and you can now simply use "url" instead.

extension URL: ExpressibleByStringLiteral {
    // By using 'StaticString' we disable string interpolation, for safety
    public init(stringLiteral value: StaticString) {
        self = URL(string: "\(value)").require(hint: "Invalid URL string literal: \(value)")
    }
}

// We can now define URLs using static string literals 🎉
let url: URL = "https://www.swiftbysundell.com"
let task = URLSession.shared.dataTask(with: "https://www.swiftbysundell.com")

// In Swift 3 or earlier, you also have to implement 2 additional initializers
extension URL {
    public init(extendedGraphemeClusterLiteral value: StaticString) {
        self.init(stringLiteral: value)
    }

    public init(unicodeScalarLiteral value: StaticString) {
        self.init(stringLiteral: value)
    }
}

To find the extension that adds the require() method on Optional that I use above, check out Require.

#27 Manipulating points, sizes and frames using math operators

✚ I'm always careful with operator overloading, but for manipulating things like sizes, points & frames I find them super useful.

extension CGSize {
    static func *(lhs: CGSize, rhs: CGFloat) -> CGSize {
        return CGSize(width: lhs.width * rhs, height: lhs.height * rhs)
    }
}

button.frame.size = image.size * 2

If you like the above idea, check out CGOperators, which contains math operator overloads for all Core Graphics' vector types.

#26 Using closure types in generic constraints

🔗 You can use closure types in generic constraints in Swift. Enables nice APIs for handling sequences of closures.

extension Sequence where Element == () -> Void {
    func callAll() {
        forEach { $0() }
    }
}

extension Sequence where Element == () -> String {
    func joinedResults(separator: String) -> String {
        return map { $0() }.joined(separator: separator)
    }
}

callbacks.callAll()
let names = nameProviders.joinedResults(separator: ", ")

(If you're using Swift 3, you have to change Element to Iterator.Element)

#25 Using associated enum values to avoid state-specific optionals

🎉 Using associated enum values is a super nice way to encapsulate mutually exclusive state info (and avoiding state-specific optionals).

// BEFORE: Lots of state-specific, optional properties

class Player {
    var isWaitingForMatchMaking: Bool
    var invitingUser: User?
    var numberOfLives: Int
    var playerDefeatedBy: Player?
    var roundDefeatedIn: Int?
}

// AFTER: All state-specific information is encapsulated in enum cases

class Player {
    enum State {
        case waitingForMatchMaking
        case waitingForInviteResponse(from: User)
        case active(numberOfLives: Int)
        case defeated(by: Player, roundNumber: Int)
    }
    
    var state: State
}

#24 Using enums for async result types

👍 I really like using enums for all async result types, even boolean ones. Self-documenting, and makes the call site a lot nicer to read too!

protocol PushNotificationService {
    // Before
    func enablePushNotifications(completionHandler: @escaping (Bool) -> Void)
    
    // After
    func enablePushNotifications(completionHandler: @escaping (PushNotificationStatus) -> Void)
}

enum PushNotificationStatus {
    case enabled
    case disabled
}

service.enablePushNotifications { status in
    if status == .enabled {
        enableNotificationsButton.removeFromSuperview()
    }
}

#23 Working on async code in a playground

🏃 Want to work on your async code in a Swift Playground? Just set needsIndefiniteExecution to true to keep it running:

import PlaygroundSupport

PlaygroundPage.current.needsIndefiniteExecution = true

DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
    let greeting = "Hello after 3 seconds"
    print(greeting)
}

To stop the playground from executing, simply call PlaygroundPage.current.finishExecution().

#22 Overriding self with a weak reference

💦 Avoid memory leaks when accidentially refering to self in closures by overriding it locally with a weak reference:

Swift >= 4.2

dataLoader.loadData(from: url) { [weak self] result in
    guard let self = self else { 
        return 
    }

    self.cache(result)
    
    ...

Swift < 4.2

dataLoader.loadData(from: url) { [weak self] result in
    guard let `self` = self else {
        return
    }

    self.cache(result)
    
    ...

Note that the reason the above currently works is because of a compiler bug (which I hope gets turned into a properly supported feature soon).

#21 Using DispatchWorkItem

🕓 Using dispatch work items you can easily cancel a delayed asynchronous GCD task if you no longer need it:

let workItem = DispatchWorkItem {
    // Your async code goes in here
}

// Execute the work item after 1 second
DispatchQueue.main.asyncAfter(deadline: .now() + 1, execute: workItem)

// You can cancel the work item if you no longer need it
workItem.cancel()

#20 Combining a sequence of functions

➕ While working on a new Swift developer tool (to be open sourced soon 😉), I came up with a pretty neat way of organizing its sequence of operations, by combining their functions into a closure:

internal func +<A, B, C>(lhs: @escaping (A) throws -> B,
                         rhs: @escaping (B) throws -> C) -> (A) throws -> C {
    return { try rhs(lhs($0)) }
}

public func run() throws {
    try (determineTarget + build + analyze + output)()
}

If you're familiar with the functional programming world, you might know the above technique as the pipe operator (thanks to Alexey Demedreckiy for pointing this out!)

#19 Chaining optionals with map() and flatMap()

🗺 Using map() and flatMap() on optionals you can chain multiple operations without having to use lengthy if lets or guards:

// BEFORE

guard let string = argument(at: 1) else {
    return
}

guard let url = URL(string: string) else {
    return
}

handle(url)

// AFTER

argument(at: 1).flatMap(URL.init).map(handle)

#18 Using self-executing closures for lazy properties

🚀 Using self-executing closures is a great way to encapsulate lazy property initialization:

class StoreViewController: UIViewController {
    private lazy var collectionView: UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        let view = UICollectionView(frame: self.view.bounds, collectionViewLayout: layout)
        view.delegate = self
        view.dataSource = self
        return view
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.addSubview(collectionView)
    }
}

#17 Speeding up Swift package tests

⚡️ You can speed up your Swift package tests using the --parallel flag. For Marathon, the tests execute 3 times faster that way!

swift test --parallel

#16 Avoiding mocking UserDefaults

🛠 Struggling with mocking UserDefaults in a test? The good news is: you don't need mocking - just create a real instance:

class LoginTests: XCTestCase {
    private var userDefaults: UserDefaults!
    private var manager: LoginManager!
    
    override func setUp() {
        super.setup()
        
        userDefaults = UserDefaults(suiteName: #file)
        userDefaults.removePersistentDomain(forName: #file)
        
        manager = LoginManager(userDefaults: userDefaults)
    }
}

#15 Using variadic parameters

👍 Using variadic parameters in Swift, you can create some really nice APIs that take a list of objects without having to use an array:

extension Canvas {
    func add(_ shapes: Shape...) {
        shapes.forEach(add)
    }
}

let circle = Circle(center: CGPoint(x: 5, y: 5), radius: 5)
let lineA = Line(start: .zero, end: CGPoint(x: 10, y: 10))
let lineB = Line(start: CGPoint(x: 0, y: 10), end: CGPoint(x: 10, y: 0))

let canvas = Canvas()
canvas.add(circle, lineA, lineB)
canvas.render()

#14 Referring to enum cases with associated values as closures

😮 Just like you can refer to a Swift function as a closure, you can do the same thing with enum cases with associated values:

enum UnboxPath {
    case key(String)
    case keyPath(String)
}

struct UserSchema {
    static let name = key("name")
    static let age = key("age")
    static let posts = key("posts")
    
    private static let key = UnboxPath.key
}

#13 Using the === operator to compare objects by instance

📈 The === operator lets you check if two objects are the same instance. Very useful when verifying that an array contains an instance in a test:

protocol InstanceEquatable: class, Equatable {}

extension InstanceEquatable {
    static func ==(lhs: Self, rhs: Self) -> Bool {
        return lhs === rhs
    }
}

extension Enemy: InstanceEquatable {}

func testDestroyingEnemy() {
    player.attack(enemy)
    XCTAssertTrue(player.destroyedEnemies.contains(enemy))
}

#12 Calling initializers with dot syntax and passing them as closures

😎 Cool thing about Swift initializers: you can call them using dot syntax and pass them as closures! Perfect for mocking dates in tests.

class Logger {
    private let storage: LogStorage
    private let dateProvider: () -> Date
    
    init(storage: LogStorage = .init(), dateProvider: @escaping () -> Date = Date.init) {
        self.storage = storage
        self.dateProvider = dateProvider
    }
    
    func log(event: Event) {
        storage.store(event: event, date: dateProvider())
    }
}

#11 Structuring UI tests as extensions on XCUIApplication

📱 Most of my UI testing logic is now categories on XCUIApplication. Makes the test cases really easy to read:

func testLoggingInAndOut() {
    XCTAssertFalse(app.userIsLoggedIn)
    
    app.launch()
    app.login()
    XCTAssertTrue(app.userIsLoggedIn)
    
    app.logout()
    XCTAssertFalse(app.userIsLoggedIn)
}

func testDisplayingCategories() {
    XCTAssertFalse(app.isDisplayingCategories)
    
    app.launch()
    app.login()
    app.goToCategories()
    XCTAssertTrue(app.isDisplayingCategories)
}

#10 Avoiding default cases in switch statements

🙂 It’s a good idea to avoid “default” cases when switching on Swift enums - it’ll “force you” to update your logic when a new case is added:

enum State {
    case loggedIn
    case loggedOut
    case onboarding
}

func handle(_ state: State) {
    switch state {
    case .loggedIn:
        showMainUI()
    case .loggedOut:
        showLoginUI()
    // Compiler error: Switch must be exhaustive
    }
}

#9 Using the guard statement in many different scopes

💂 It's really cool that you can use Swift's 'guard' statement to exit out of pretty much any scope, not only return from functions:

// You can use the 'guard' statement to...

for string in strings {
    // ...continue an iteration
    guard shouldProcess(string) else {
        continue
    }
    
    // ...or break it
    guard !shouldBreak(for: string) else {
        break
    }
    
    // ...or return
    guard !shouldReturn(for: string) else {
        return
    }
    
    // ..or throw an error
    guard string.isValid else {
        throw StringError.invalid(string)
    }
    
    // ...or exit the program
    guard !shouldExit(for: string) else {
        exit(1)
    }
}

#8 Passing functions & operators as closures

❤️ Love how you can pass functions & operators as closures in Swift. For example, it makes the syntax for sorting arrays really nice!

let array = [3, 9, 1, 4, 6, 2]
let sorted = array.sorted(by: <)

#7 Using #function for UserDefaults key consistency

🗝 Here's a neat little trick I use to get UserDefault key consistency in Swift (#function expands to the property name in getters/setters). Just remember to write a good suite of tests that'll guard you against bugs when changing property names.

extension UserDefaults {
    var onboardingCompleted: Bool {
        get { return bool(forKey: #function) }
        set { set(newValue, forKey: #function) }
    }
}

#6 Using a name already taken by the standard library

📛 Want to use a name already taken by the standard library for a nested type? No problem - just use Swift. to disambiguate:

extension Command {
    enum Error: Swift.Error {
        case missing
        case invalid(String)
    }
}

#5 Using Wrap to implement Equatable

📦 Playing around with using Wrap to implement Equatable for any type, primarily for testing:

protocol AutoEquatable: Equatable {}

extension AutoEquatable {
    static func ==(lhs: Self, rhs: Self) -> Bool {
        let lhsData = try! wrap(lhs) as Data
        let rhsData = try! wrap(rhs) as Data
        return lhsData == rhsData
    }
}

#4 Using typealiases to reduce the length of method signatures

📏 One thing that I find really useful in Swift is to use typealiases to reduce the length of method signatures in generic types:

public class PathFinder<Object: PathFinderObject> {
    public typealias Map = Object.Map
    public typealias Node = Map.Node
    public typealias Path = PathFinderPath<Object>
    
    public static func possiblePaths(for object: Object, at rootNode: Node, on map: Map) -> Path.Sequence {
        return .init(object: object, rootNode: rootNode, map: map)
    }
}

#3 Referencing either external or internal parameter name when writing docs

📖 You can reference either the external or internal parameter label when writing Swift docs - and they get parsed the same:

// EITHER:

class Foo {
    /**
    *   - parameter string: A string
    */
    func bar(with string: String) {}
}

// OR:

class Foo {
    /**
    *   - parameter with: A string
    */
    func bar(with string: String) {}
}

#2 Using auto closures

👍 Finding more and more uses for auto closures in Swift. Can enable some pretty nice APIs:

extension Dictionary {
    mutating func value(for key: Key, orAdd valueClosure: @autoclosure () -> Value) -> Value {
        if let value = self[key] {
            return value
        }
        
        let value = valueClosure()
        self[key] = value
        return value
    }
}

#1 Namespacing with nested types

🚀 I’ve started to become a really big fan of nested types in Swift. Love the additional namespacing it gives you!

public struct Map {
    public struct Model {
        public let size: Size
        public let theme: Theme
        public var terrain: [Position : Terrain.Model]
        public var units: [Position : Unit.Model]
        public var buildings: [Position : Building.Model]
    }
    
    public enum Direction {
        case up
        case right
        case down
        case left
    }
    
    public struct Position {
        public var x: Int
        public var y: Int
    }
    
    public enum Size: String {
        case small = "S"
        case medium = "M"
        case large = "L"
        case extraLarge = "XL"
    }
}

Download Details:

Author: JohnSundell
Source code: https://github.com/JohnSundell/SwiftTips

License: MIT license
#swift 

A Collection Of Swift Tips & Tricks That I've Shared on Twitter

Swift Tips: A Collection Useful Tips for The Swift Language

SwiftTips

The following is a collection of tips I find to be useful when working with the Swift language. More content is available on my Twitter account!

Property Wrappers as Debugging Tools

Property Wrappers allow developers to wrap properties with specific behaviors, that will be seamlessly triggered whenever the properties are accessed.

While their primary use case is to implement business logic within our apps, it's also possible to use Property Wrappers as debugging tools!

For example, we could build a wrapper called @History, that would be added to a property while debugging and would keep track of all the values set to this property.

import Foundation

@propertyWrapper
struct History<Value> {
    private var value: Value
    private(set) var history: [Value] = []

    init(wrappedValue: Value) {
        self.value = wrappedValue
    }
    
    var wrappedValue: Value {
        get { value }

        set {
            history.append(value)
            value = newValue
        }
    }
    
    var projectedValue: Self {
        return self
    }
}

// We can then decorate our business code
// with the `@History` wrapper
struct User {
    @History var name: String = ""
}

var user = User()

// All the existing call sites will still
// compile, without the need for any change
user.name = "John"
user.name = "Jane"

// But now we can also access an history of
// all the previous values!
user.$name.history // ["", "John"]

Localization through String interpolation

Swift 5 gave us the possibility to define our own custom String interpolation methods.

This feature can be used to power many use cases, but there is one that is guaranteed to make sense in most projects: localizing user-facing strings.

import Foundation

extension String.StringInterpolation {
    mutating func appendInterpolation(localized key: String, _ args: CVarArg...) {
        let localized = String(format: NSLocalizedString(key, comment: ""), arguments: args)
        appendLiteral(localized)
    }
}


/*
 Let's assume that this is the content of our Localizable.strings:
 
 "welcome.screen.greetings" = "Hello %@!";
 */

let userName = "John"
print("\(localized: "welcome.screen.greetings", userName)") // Hello John!

Implementing pseudo-inheritance between structs

If you’ve always wanted to use some kind of inheritance mechanism for your structs, Swift 5.1 is going to make you very happy!

Using the new KeyPath-based dynamic member lookup, you can implement some pseudo-inheritance, where a type inherits the API of another one 🎉

(However, be careful, I’m definitely not advocating inheritance as a go-to solution 🙃)

import Foundation

protocol Inherits {
    associatedtype SuperType
    
    var `super`: SuperType { get }
}

extension Inherits {
    subscript<T>(dynamicMember keyPath: KeyPath<SuperType, T>) -> T {
        return self.`super`[keyPath: keyPath]
    }
}

struct Person {
    let name: String
}

@dynamicMemberLookup
struct User: Inherits {
    let `super`: Person
    
    let login: String
    let password: String
}

let user = User(super: Person(name: "John Appleseed"), login: "Johnny", password: "1234")

user.name // "John Appleseed"
user.login // "Johnny"

Composing NSAttributedString through a Function Builder

Swift 5.1 introduced Function Builders: a great tool for building custom DSL syntaxes, like SwiftUI. However, one doesn't need to be building a full-fledged DSL in order to leverage them.

For example, it's possible to write a simple Function Builder, whose job will be to compose together individual instances of NSAttributedString through a nicer syntax than the standard API.

import UIKit

@_functionBuilder
class NSAttributedStringBuilder {
    static func buildBlock(_ components: NSAttributedString...) -> NSAttributedString {
        let result = NSMutableAttributedString(string: "")
        
        return components.reduce(into: result) { (result, current) in result.append(current) }
    }
}

extension NSAttributedString {
    class func composing(@NSAttributedStringBuilder _ parts: () -> NSAttributedString) -> NSAttributedString {
        return parts()
    }
}

let result = NSAttributedString.composing {
    NSAttributedString(string: "Hello",
                       attributes: [.font: UIFont.systemFont(ofSize: 24),
                                    .foregroundColor: UIColor.red])
    NSAttributedString(string: " world!",
                       attributes: [.font: UIFont.systemFont(ofSize: 20),
                                    .foregroundColor: UIColor.orange])
}

Using switch and if as expressions

Contrary to other languages, like Kotlin, Swift does not allow switch and if to be used as expressions. Meaning that the following code is not valid Swift:

let constant = if condition {
                  someValue
               } else {
                  someOtherValue
               }

A common solution to this problem is to wrap the if or switch statement within a closure, that will then be immediately called. While this approach does manage to achieve the desired goal, it makes for a rather poor syntax.

To avoid the ugly trailing () and improve on the readability, you can define a resultOf function, that will serve the exact same purpose, in a more elegant way.

import Foundation

func resultOf<T>(_ code: () -> T) -> T {
    return code()
}

let randomInt = Int.random(in: 0...3)

let spelledOut: String = resultOf {
    switch randomInt {
    case 0:
        return "Zero"
    case 1:
        return "One"
    case 2:
        return "Two"
    case 3:
        return "Three"
    default:
        return "Out of range"
    }
}

print(spelledOut)

Avoiding double negatives within guard statements

A guard statement is a very convenient way for the developer to assert that a condition is met, in order for the execution of the program to keep going.

However, since the body of a guard statement is meant to be executed when the condition evaluates to false, the use of the negation (!) operator within the condition of a guard statement can make the code hard to read, as it becomes a double negative.

A nice trick to avoid such double negatives is to encapsulate the use of the ! operator within a new property or function, whose name does not include a negative.

import Foundation

extension Collection {
    var hasElements: Bool {
        return !isEmpty
    }
}

let array = Bool.random() ? [1, 2, 3] : []

guard array.hasElements else { fatalError("array was empty") }

print(array)

Defining a custom init without loosing the compiler-generated one

It's common knowledge for Swift developers that, when you define a struct, the compiler is going to automatically generate a memberwise init for you. That is, unless you also define an init of your own. Because then, the compiler won't generate any memberwise init.

Yet, there are many instances where we might enjoy the opportunity to get both. As it turns out, this goal is quite easy to achieve: you just need to define your own init in an extension rather than inside the type definition itself.

import Foundation

struct Point {
    let x: Int
    let y: Int
}

extension Point {
    init() {
        x = 0
        y = 0
    }
}

let usingDefaultInit = Point(x: 4, y: 3)
let usingCustomInit = Point()

Implementing a namespace through an empty enum

Swift does not really have an out-of-the-box support of namespaces. One could argue that a Swift module can be seen as a namespace, but creating a dedicated Framework for this sole purpose can legitimately be regarded as overkill.

Some developers have taken the habit to use a struct which only contains static fields to implement a namespace. While this does the job, it requires us to remember to implement an empty private init(), because it wouldn't make sense for such a struct to be instantiated.

It's actually possible to take this approach one step further, by replacing the struct with an enum. While it might seem weird to have an enum with no case, it's actually a very idiomatic way to declare a type that cannot be instantiated.

import Foundation

enum NumberFormatterProvider {
    static var currencyFormatter: NumberFormatter {
        let formatter = NumberFormatter()
        formatter.numberStyle = .currency
        formatter.roundingIncrement = 0.01
        return formatter
    }
    
    static var decimalFormatter: NumberFormatter {
        let formatter = NumberFormatter()
        formatter.numberStyle = .decimal
        formatter.decimalSeparator = ","
        return formatter
    }
}

NumberFormatterProvider() // ❌ impossible to instantiate by mistake

NumberFormatterProvider.currencyFormatter.string(from: 2.456) // $2.46
NumberFormatterProvider.decimalFormatter.string(from: 2.456) // 2,456

Using Never to represent impossible code paths

Never is quite a peculiar type in the Swift Standard Library: it is defined as an empty enum enum Never { }.

While this might seem odd at first glance, it actually yields a very interesting property: it makes it a type that cannot be constructed (i.e. it possesses no instances).

This way, Never can be used as a generic parameter to let the compiler know that a particular feature will not be used.

import Foundation

enum Result<Value, Error> {
    case success(value: Value)
    case failure(error: Error)
}

func willAlwaysSucceed(_ completion: @escaping ((Result<String, Never>) -> Void)) {
    completion(.success(value: "Call was successful"))
}

willAlwaysSucceed( { result in
    switch result {
    case .success(let value):
        print(value)
    // the compiler knows that the `failure` case cannot happen
    // so it doesn't require us to handle it.
    }
})

Providing a default value to a Decodable enum

Swift's Codable framework does a great job at seamlessly decoding entities from a JSON stream. However, when we integrate web-services, we are sometimes left to deal with JSONs that require behaviors that Codable does not provide out-of-the-box.

For instance, we might have a string-based or integer-based enum, and be required to set it to a default value when the data found in the JSON does not match any of its cases.

We might be tempted to implement this via an extensive switch statement over all the possible cases, but there is a much shorter alternative through the initializer init?(rawValue:):

import Foundation

enum State: String, Decodable {
    case active
    case inactive
    case undefined
    
    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        let decodedString = try container.decode(String.self)
        
        self = State(rawValue: decodedString) ?? .undefined
    }
}

let data = """
["active", "inactive", "foo"]
""".data(using: .utf8)!

let decoded = try! JSONDecoder().decode([State].self, from: data)

print(decoded) // [State.active, State.inactive, State.undefined]

Another lightweight dependency injection through default values for function parameters

Dependency injection boils down to a simple idea: when an object requires a dependency, it shouldn't create it by itself, but instead it should be given a function that does it for him.

Now the great thing with Swift is that, not only can a function take another function as a parameter, but that parameter can also be given a default value.

When you combine both those features, you can end up with a dependency injection pattern that is both lightweight on boilerplate, but also type safe.

import Foundation

protocol Service {
    func call() -> String
}

class ProductionService: Service {
    func call() -> String {
        return "This is the production"
    }
}

class MockService: Service {
    func call() -> String {
        return "This is a mock"
    }
}

typealias Provider<T> = () -> T

class Controller {
    
    let service: Service
    
    init(serviceProvider: Provider<Service> = { return ProductionService() }) {
        self.service = serviceProvider()
    }
    
    func work() {
        print(service.call())
    }
}

let productionController = Controller()
productionController.work() // prints "This is the production"

let mockedController = Controller(serviceProvider: { return MockService() })
mockedController.work() // prints "This is a mock"

Lightweight dependency injection through protocol-oriented programming

Singletons are pretty bad. They make your architecture rigid and tightly coupled, which then results in your code being hard to test and refactor. Instead of using singletons, your code should rely on dependency injection, which is a much more architecturally sound approach.

But singletons are so easy to use, and dependency injection requires us to do extra-work. So maybe, for simple situations, we could find an in-between solution?

One possible solution is to rely on one of Swift's most know features: protocol-oriented programming. Using a protocol, we declare and access our dependency. We then store it in a private singleton, and perform the injection through an extension of said protocol.

This way, our code will indeed be decoupled from its dependency, while at the same time keeping the boilerplate to a minimum.

import Foundation

protocol Formatting {
    var formatter: NumberFormatter { get }
}

private let sharedFormatter: NumberFormatter = {
    let sharedFormatter = NumberFormatter()
    sharedFormatter.numberStyle = .currency
    return sharedFormatter
}()

extension Formatting {
    var formatter: NumberFormatter { return sharedFormatter }
}

class ViewModel: Formatting {
    var displayableAmount: String?
    
    func updateDisplay(to amount: Double) {
        displayableAmount = formatter.string(for: amount)
    }
}

let viewModel = ViewModel()

viewModel.updateDisplay(to: 42000.45)
viewModel.displayableAmount // "$42,000.45"

Getting rid of overabundant [weak self] and guard

Callbacks are a part of almost all iOS apps, and as frameworks such as RxSwift keep gaining in popularity, they become ever more present in our codebase.

Seasoned Swift developers are aware of the potential memory leaks that @escaping callbacks can produce, so they make real sure to always use [weak self], whenever they need to use self inside such a context. And when they need to have self be non-optional, they then add a guard statement along.

Consequently, this syntax of a [weak self] followed by a guard rapidly tends to appear everywhere in the codebase. The good thing is that, through a little protocol-oriented trick, it's actually possible to get rid of this tedious syntax, without loosing any of its benefits!

import Foundation
import PlaygroundSupport

PlaygroundPage.current.needsIndefiniteExecution = true

protocol Weakifiable: class { }

extension Weakifiable {
    func weakify(_ code: @escaping (Self) -> Void) -> () -> Void {
        return { [weak self] in
            guard let self = self else { return }
            
            code(self)
        }
    }
    
    func weakify<T>(_ code: @escaping (T, Self) -> Void) -> (T) -> Void {
        return { [weak self] arg in
            guard let self = self else { return }
            
            code(arg, self)
        }
    }
}

extension NSObject: Weakifiable { }

class Producer: NSObject {
    
    deinit {
        print("deinit Producer")
    }
    
    private var handler: (Int) -> Void = { _ in }
    
    func register(handler: @escaping (Int) -> Void) {
        self.handler = handler
        
        DispatchQueue.main.asyncAfter(deadline: .now() + 1.0, execute: { self.handler(42) })
    }
}

class Consumer: NSObject {
    
    deinit {
        print("deinit Consumer")
    }
    
    let producer = Producer()
    
    func consume() {
        producer.register(handler: weakify { result, strongSelf in
            strongSelf.handle(result)
        })
    }
    
    private func handle(_ result: Int) {
        print("🎉 \(result)")
    }
}

var consumer: Consumer? = Consumer()

consumer?.consume()

DispatchQueue.main.asyncAfter(deadline: .now() + 2.0, execute: { consumer = nil })

// This code prints:
// 🎉 42
// deinit Consumer
// deinit Producer

Solving callback hell with function composition

Asynchronous functions are a big part of iOS APIs, and most developers are familiar with the challenge they pose when one needs to sequentially call several asynchronous APIs.

This often results in callbacks being nested into one another, a predicament often referred to as callback hell.

Many third-party frameworks are able to tackle this issue, for instance RxSwift or PromiseKit. Yet, for simple instances of the problem, there is no need to use such big guns, as it can actually be solved with simple function composition.

import Foundation

typealias CompletionHandler<Result> = (Result?, Error?) -> Void

infix operator ~>: MultiplicationPrecedence

func ~> <T, U>(_ first: @escaping (CompletionHandler<T>) -> Void, _ second: @escaping (T, CompletionHandler<U>) -> Void) -> (CompletionHandler<U>) -> Void {
    return { completion in
        first({ firstResult, error in
            guard let firstResult = firstResult else { completion(nil, error); return }
            
            second(firstResult, { (secondResult, error) in
                completion(secondResult, error)
            })
        })
    }
}

func ~> <T, U>(_ first: @escaping (CompletionHandler<T>) -> Void, _ transform: @escaping (T) -> U) -> (CompletionHandler<U>) -> Void {
    return { completion in
        first({ result, error in
            guard let result = result else { completion(nil, error); return }
            
            completion(transform(result), nil)
        })
    }
}

func service1(_ completionHandler: CompletionHandler<Int>) {
    completionHandler(42, nil)
}

func service2(arg: String, _ completionHandler: CompletionHandler<String>) {
    completionHandler("🎉 \(arg)", nil)
}

let chainedServices = service1
    ~> { int in return String(int / 2) }
    ~> service2

chainedServices({ result, _ in
    guard let result = result else { return }
    
    print(result) // Prints: 🎉 21
})

Transform an asynchronous function into a synchronous one

Asynchronous functions are a great way to deal with future events without blocking a thread. Yet, there are times where we would like them to behave in exactly such a blocking way.

Think about writing unit tests and using mocked network calls. You will need to add complexity to your test in order to deal with asynchronous functions, whereas synchronous ones would be much easier to manage.

Thanks to Swift proficiency in the functional paradigm, it is possible to write a function whose job is to take an asynchronous function and transform it into a synchronous one.

import Foundation

func makeSynchrone<A, B>(_ asyncFunction: @escaping (A, (B) -> Void) -> Void) -> (A) -> B {
    return { arg in
        let lock = NSRecursiveLock()
        
        var result: B? = nil
        
        asyncFunction(arg) {
            result = $0
            lock.unlock()
        }
        
        lock.lock()
        
        return result!
    }
}

func myAsyncFunction(arg: Int, completionHandler: (String) -> Void) {
    completionHandler("🎉 \(arg)")
}

let syncFunction = makeSynchrone(myAsyncFunction)

print(syncFunction(42)) // prints 🎉 42

Using KeyPaths instead of closures

Closures are a great way to interact with generic APIs, for instance APIs that allow to manipulate data structures through the use of generic functions, such as filter() or sorted().

The annoying part is that closures tend to clutter your code with many instances of {, } and $0, which can quickly undermine its readably.

A nice alternative for a cleaner syntax is to use a KeyPath instead of a closure, along with an operator that will deal with transforming the provided KeyPath in a closure.

import Foundation

prefix operator ^

prefix func ^ <Element, Attribute>(_ keyPath: KeyPath<Element, Attribute>) -> (Element) -> Attribute {
    return { element in element[keyPath: keyPath] }
}

struct MyData {
    let int: Int
    let string: String
}

let data = [MyData(int: 2, string: "Foo"), MyData(int: 4, string: "Bar")]

data.map(^\.int) // [2, 4]
data.map(^\.string) // ["Foo", "Bar"]

Bringing some type-safety to a userInfo Dictionary

Many iOS APIs still rely on a userInfo Dictionary to handle use-case specific data. This Dictionary usually stores untyped values, and is declared as follows: [String: Any] (or sometimes [AnyHashable: Any].

Retrieving data from such a structure will involve some conditional casting (via the as? operator), which is prone to both errors and repetitions. Yet, by introducing a custom subscript, it's possible to encapsulate all the tedious logic, and end-up with an easier and more robust API.

import Foundation

typealias TypedUserInfoKey<T> = (key: String, type: T.Type)

extension Dictionary where Key == String, Value == Any {
    subscript<T>(_ typedKey: TypedUserInfoKey<T>) -> T? {
        return self[typedKey.key] as? T
    }
}

let userInfo: [String : Any] = ["Foo": 4, "Bar": "forty-two"]

let integerTypedKey = TypedUserInfoKey(key: "Foo", type: Int.self)
let intValue = userInfo[integerTypedKey] // returns 4
type(of: intValue) // returns Int?

let stringTypedKey = TypedUserInfoKey(key: "Bar", type: String.self)
let stringValue = userInfo[stringTypedKey] // returns "forty-two"
type(of: stringValue) // returns String?

Lightweight data-binding for an MVVM implementation

MVVM is a great pattern to separate business logic from presentation logic. The main challenge to make it work, is to define a mechanism for the presentation layer to be notified of model updates.

RxSwift is a perfect choice to solve such a problem. Yet, some developers don't feel confortable with leveraging a third-party library for such a central part of their architecture.

For those situation, it's possible to define a lightweight Variable type, that will make the MVVM pattern very easy to use!

import Foundation

class Variable<Value> {
    var value: Value {
        didSet {
            onUpdate?(value)
        }
    }
    
    var onUpdate: ((Value) -> Void)? {
        didSet {
            onUpdate?(value)
        }
    }
    
    init(_ value: Value, _ onUpdate: ((Value) -> Void)? = nil) {
        self.value = value
        self.onUpdate = onUpdate
        self.onUpdate?(value)
    }
}

let variable: Variable<String?> = Variable(nil)

variable.onUpdate = { data in
    if let data = data {
        print(data)
    }
}

variable.value = "Foo"
variable.value = "Bar"

// prints:
// Foo
// Bar

Using typealias to its fullest

The keyword typealias allows developers to give a new name to an already existing type. For instance, Swift defines Void as a typealias of (), the empty tuple.

But a less known feature of this mechanism is that it allows to assign concrete types for generic parameters, or to rename them. This can help make the semantics of generic types much clearer, when used in specific use cases.

import Foundation

enum Either<Left, Right> {
    case left(Left)
    case right(Right)
}

typealias Result<Value> = Either<Value, Error>

typealias IntOrString = Either<Int, String>

Writing an interruptible overload of forEach

Iterating through objects via the forEach(_:) method is a great alternative to the classic for loop, as it allows our code to be completely oblivious of the iteration logic. One limitation, however, is that forEach(_:) does not allow to stop the iteration midway.

Taking inspiration from the Objective-C implementation, we can write an overload that will allow the developer to stop the iteration, if needed.

import Foundation

extension Sequence {
    func forEach(_ body: (Element, _ stop: inout Bool) throws -> Void) rethrows {
        var stop = false
        for element in self {
            try body(element, &stop)
            
            if stop {
                return
            }
        }
    }
}

["Foo", "Bar", "FooBar"].forEach { element, stop in
    print(element)
    stop = (element == "Bar")
}

// Prints:
// Foo
// Bar

Optimizing the use of reduce()

Functional programing is a great way to simplify a codebase. For instance, reduce is an alternative to the classic for loop, without most the boilerplate. Unfortunately, simplicity often comes at the price of performance.

Consider that you want to remove duplicate values from a Sequence. While reduce() is a perfectly fine way to express this computation, the performance will be sub optimal, because of all the unnecessary Array copying that will happen every time its closure gets called.

That's when reduce(into:_:) comes into play. This version of reduce leverages the capacities of copy-on-write type (such as Array or Dictionnary) in order to avoid unnecessary copying, which results in a great performance boost.

import Foundation

func time(averagedExecutions: Int = 1, _ code: () -> Void) {
    let start = Date()
    for _ in 0..<averagedExecutions { code() }
    let end = Date()
    
    let duration = end.timeIntervalSince(start) / Double(averagedExecutions)
    
    print("time: \(duration)")
}

let data = (1...1_000).map { _ in Int(arc4random_uniform(256)) }


// runs in 0.63s
time {
    let noDuplicates: [Int] = data.reduce([], { $0.contains($1) ? $0 : $0 + [$1] })
}

// runs in 0.15s
time {
    let noDuplicates: [Int] = data.reduce(into: [], { if !$0.contains($1) { $0.append($1) } } )
}

Avoiding hardcoded reuse identifiers

UI components such as UITableView and UICollectionView rely on reuse identifiers in order to efficiently recycle the views they display. Often, those reuse identifiers take the form of a static hardcoded String, that will be used for every instance of their class.

Through protocol-oriented programing, it's possible to avoid those hardcoded values, and instead use the name of the type as a reuse identifier.

import Foundation
import UIKit

protocol Reusable {
    static var reuseIdentifier: String { get }
}

extension Reusable {
    static var reuseIdentifier: String {
        return String(describing: self)
    }
}

extension UITableViewCell: Reusable { }

extension UITableView {
    func register<T: UITableViewCell>(_ class: T.Type) {
        register(`class`, forCellReuseIdentifier: T.reuseIdentifier)
    }
    func dequeueReusableCell<T: UITableViewCell>(for indexPath: IndexPath) -> T {
        return dequeueReusableCell(withIdentifier: T.reuseIdentifier, for: indexPath) as! T
    }
}

class MyCell: UITableViewCell { }

let tableView = UITableView()

tableView.register(MyCell.self)
let myCell: MyCell = tableView.dequeueReusableCell(for: [0, 0])

Defining a union type

The C language has a construct called union, that allows a single variable to hold values from different types. While Swift does not provide such a construct, it provides enums with associated values, which allows us to define a type called Either that implements a union of two types.

import Foundation

enum Either<A, B> {
    case left(A)
    case right(B)
    
    func either(ifLeft: ((A) -> Void)? = nil, ifRight: ((B) -> Void)? = nil) {
        switch self {
        case let .left(a):
            ifLeft?(a)
        case let .right(b):
            ifRight?(b)
        }
    }
}

extension Bool { static func random() -> Bool { return arc4random_uniform(2) == 0 } }

var intOrString: Either<Int, String> = Bool.random() ? .left(2) : .right("Foo")

intOrString.either(ifLeft: { print($0 + 1) }, ifRight: { print($0 + "Bar") })

If you're interested by this kind of data structure, I strongly recommend that you learn more about Algebraic Data Types.

Asserting that classes have associated NIBs and vice-versa

Most of the time, when we create a .xib file, we give it the same name as its associated class. From that, if we later refactor our code and rename such a class, we run the risk of forgetting to rename the associated .xib.

While the error will often be easy to catch, if the .xib is used in a remote section of its app, it might go unnoticed for sometime. Fortunately it's possible to build custom test predicates that will assert that 1) for a given class, there exists a .nib with the same name in a given Bundle, 2) for all the .nib in a given Bundle, there exists a class with the same name.

import XCTest

public func XCTAssertClassHasNib(_ class: AnyClass, bundle: Bundle, file: StaticString = #file, line: UInt = #line) {
    let associatedNibURL = bundle.url(forResource: String(describing: `class`), withExtension: "nib")
    
    XCTAssertNotNil(associatedNibURL, "Class \"\(`class`)\" has no associated nib file", file: file, line: line)
}

public func XCTAssertNibHaveClasses(_ bundle: Bundle, file: StaticString = #file, line: UInt = #line) {
    guard let bundleName = bundle.infoDictionary?["CFBundleName"] as? String,
        let basePath = bundle.resourcePath,
        let enumerator = FileManager.default.enumerator(at: URL(fileURLWithPath: basePath),
                                                    includingPropertiesForKeys: nil,
                                                    options: [.skipsHiddenFiles, .skipsSubdirectoryDescendants]) else { return }
    
    var nibFilesURLs = [URL]()
    
    for case let fileURL as URL in enumerator {
        if fileURL.pathExtension.uppercased() == "NIB" {
            nibFilesURLs.append(fileURL)
        }
    }
    
    nibFilesURLs.map { $0.lastPathComponent }
        .compactMap { $0.split(separator: ".").first }
        .map { String($0) }
        .forEach {
            let associatedClass: AnyClass? = bundle.classNamed("\(bundleName).\($0)")
            
            XCTAssertNotNil(associatedClass, "File \"\($0).nib\" has no associated class", file: file, line: line)
        }
}

XCTAssertClassHasNib(MyFirstTableViewCell.self, bundle: Bundle(for: AppDelegate.self))
XCTAssertClassHasNib(MySecondTableViewCell.self, bundle: Bundle(for: AppDelegate.self))
        
XCTAssertNibHaveClasses(Bundle(for: AppDelegate.self))

Many thanks Benjamin Lavialle for coming up with the idea behind the second test predicate.

Small footprint type-erasing with functions

Seasoned Swift developers know it: a protocol with associated type (PAT) "can only be used as a generic constraint because it has Self or associated type requirements". When we really need to use a PAT to type a variable, the goto workaround is to use a type-erased wrapper.

While this solution works perfectly, it requires a fair amount of boilerplate code. In instances where we are only interested in exposing one particular function of the PAT, a shorter approach using function types is possible.

import Foundation
import UIKit

protocol Configurable {
    associatedtype Model
    
    func configure(with model: Model)
}

typealias Configurator<Model> = (Model) -> ()

extension UILabel: Configurable {
    func configure(with model: String) {
        self.text = model
    }
}

let label = UILabel()
let configurator: Configurator<String> = label.configure

configurator("Foo")

label.text // "Foo"

Performing animations sequentially

UIKit exposes a very powerful and simple API to perform view animations. However, this API can become a little bit quirky to use when we want to perform animations sequentially, because it involves nesting closure within one another, which produces notoriously hard to maintain code.

Nonetheless, it's possible to define a rather simple class, that will expose a really nicer API for this particular use case 👌

import Foundation
import UIKit

class AnimationSequence {
    typealias Animations = () -> Void
    
    private let current: Animations
    private let duration: TimeInterval
    private var next: AnimationSequence? = nil
    
    init(animations: @escaping Animations, duration: TimeInterval) {
        self.current = animations
        self.duration = duration
    }
    
    @discardableResult func append(animations: @escaping Animations, duration: TimeInterval) -> AnimationSequence {
        var lastAnimation = self
        while let nextAnimation = lastAnimation.next {
            lastAnimation = nextAnimation
        }
        lastAnimation.next = AnimationSequence(animations: animations, duration: duration)
        return self
    }
    
    func run() {
        UIView.animate(withDuration: duration, animations: current, completion: { finished in
            if finished, let next = self.next {
                next.run()
            }
        })
    }
}

var firstView = UIView()
var secondView = UIView()

firstView.alpha = 0
secondView.alpha = 0

AnimationSequence(animations: { firstView.alpha = 1.0 }, duration: 1)
            .append(animations: { secondView.alpha = 1.0 }, duration: 0.5)
            .append(animations: { firstView.alpha = 0.0 }, duration: 2.0)
            .run()

Debouncing a function call

Debouncing is a very useful tool when dealing with UI inputs. Consider a search bar, whose content is used to query an API. It wouldn't make sense to perform a request for every character the user is typing, because as soon as a new character is entered, the result of the previous request has become irrelevant.

Instead, our code will perform much better if we "debounce" the API call, meaning that we will wait until some delay has passed, without the input being modified, before actually performing the call.

import Foundation

func debounced(delay: TimeInterval, queue: DispatchQueue = .main, action: @escaping (() -> Void)) -> () -> Void {
    var workItem: DispatchWorkItem?
    
    return {
        workItem?.cancel()
        workItem = DispatchWorkItem(block: action)
        queue.asyncAfter(deadline: .now() + delay, execute: workItem!)
    }
}

let debouncedPrint = debounced(delay: 1.0) { print("Action performed!") }

debouncedPrint()
debouncedPrint()
debouncedPrint()

// After a 1 second delay, this gets
// printed only once to the console:

// Action performed!

Providing useful operators for Optional booleans

When we need to apply the standard boolean operators to Optional booleans, we often end up with a syntax unnecessarily crowded with unwrapping operations. By taking a cue from the world of three-valued logics, we can define a couple operators that make working with Bool? values much nicer.

import Foundation

func && (lhs: Bool?, rhs: Bool?) -> Bool? {
    switch (lhs, rhs) {
    case (false, _), (_, false):
        return false
    case let (unwrapLhs?, unwrapRhs?):
        return unwrapLhs && unwrapRhs
    default:
        return nil
    }
}

func || (lhs: Bool?, rhs: Bool?) -> Bool? {
    switch (lhs, rhs) {
    case (true, _), (_, true):
        return true
    case let (unwrapLhs?, unwrapRhs?):
        return unwrapLhs || unwrapRhs
    default:
        return nil
    }
}

false && nil // false
true && nil // nil
[true, nil, false].reduce(true, &&) // false

nil || true // true
nil || false // nil
[true, nil, false].reduce(false, ||) // true

Removing duplicate values from a Sequence

Transforming a Sequence in order to remove all the duplicate values it contains is a classic use case. To implement it, one could be tempted to transform the Sequence into a Set, then back to an Array. The downside with this approach is that it will not preserve the order of the sequence, which can definitely be a dealbreaker. Using reduce() it is possible to provide a concise implementation that preserves ordering:

import Foundation

extension Sequence where Element: Equatable {
    func duplicatesRemoved() -> [Element] {
        return reduce([], { $0.contains($1) ? $0 : $0 + [$1] })
    }
}

let data = [2, 5, 2, 3, 6, 5, 2]

data.duplicatesRemoved() // [2, 5, 3, 6]

Shorter syntax to deal with optional strings

Optional strings are very common in Swift code, for instance many objects from UIKit expose the text they display as a String?. Many times you will need to manipulate this data as an unwrapped String, with a default value set to the empty string for nil cases.

While the nil-coalescing operator (e.g. ??) is a perfectly fine way to a achieve this goal, defining a computed variable like orEmpty can help a lot in cleaning the syntax.

import Foundation
import UIKit

extension Optional where Wrapped == String {
    var orEmpty: String {
        switch self {
        case .some(let value):
            return value
        case .none:
            return ""
        }
    }
}

func doesNotWorkWithOptionalString(_ param: String) {
    // do something with `param`
}

let label = UILabel()
label.text = "This is some text."

doesNotWorkWithOptionalString(label.text.orEmpty)

Encapsulating background computation and UI update

Every seasoned iOS developers knows it: objects from UIKit can only be accessed from the main thread. Any attempt to access them from a background thread is a guaranteed crash.

Still, running a costly computation on the background, and then using it to update the UI can be a common pattern.

In such cases you can rely on asyncUI to encapsulate all the boilerplate code.

import Foundation
import UIKit

func asyncUI<T>(_ computation: @autoclosure @escaping () -> T, qos: DispatchQoS.QoSClass = .userInitiated, _ completion: @escaping (T) -> Void) {
    DispatchQueue.global(qos: qos).async {
        let value = computation()
        DispatchQueue.main.async {
            completion(value)
        }
    }
}

let label = UILabel()

func costlyComputation() -> Int { return (0..<10_000).reduce(0, +) }

asyncUI(costlyComputation()) { value in
    label.text = "\(value)"
}

Retrieving all the necessary data to build a debug view

A debug view, from which any controller of an app can be instantiated and pushed on the navigation stack, has the potential to bring some real value to a development process. A requirement to build such a view is to have a list of all the classes from a given Bundle that inherit from UIViewController. With the following extension, retrieving this list becomes a piece of cake 🍰

import Foundation
import UIKit
import ObjectiveC

extension Bundle {
    func viewControllerTypes() -> [UIViewController.Type] {
        guard let bundlePath = self.executablePath else { return [] }
        
        var size: UInt32 = 0
        var rawClassNames: UnsafeMutablePointer<UnsafePointer<Int8>>!
        var parsedClassNames = [String]()
        
        rawClassNames = objc_copyClassNamesForImage(bundlePath, &size)
        
        for index in 0..<size {
            let className = rawClassNames[Int(index)]
            
            if let name = NSString.init(utf8String:className) as String?,
                NSClassFromString(name) is UIViewController.Type {
                parsedClassNames.append(name)
            }
        }
        
        return parsedClassNames
            .sorted()
            .compactMap { NSClassFromString($0) as? UIViewController.Type }
    }
}

// Fetch all view controller types in UIKit
Bundle(for: UIViewController.self).viewControllerTypes()

I share the credit for this tip with Benoît Caron.

Defining a function to map over dictionaries

Update As it turns out, map is actually a really bad name for this function, because it does not preserve composition of transformations, a property that is required to fit the definition of a real map function.

Surprisingly enough, the standard library doesn't define a map() function for dictionaries that allows to map both keys and values into a new Dictionary. Nevertheless, such a function can be helpful, for instance when converting data across different frameworks.

import Foundation

extension Dictionary {
    func map<T: Hashable, U>(_ transform: (Key, Value) throws -> (T, U)) rethrows -> [T: U] {
        var result: [T: U] = [:]
        
        for (key, value) in self {
            let (transformedKey, transformedValue) = try transform(key, value)
            result[transformedKey] = transformedValue
        }
        
        return result
    }
}

let data = [0: 5, 1: 6, 2: 7]
data.map { ("\($0)", $1 * $1) } // ["2": 49, "0": 25, "1": 36]

A shorter syntax to remove nil values

Swift provides the function compactMap(), that can be used to remove nil values from a Sequence of optionals when calling it with an argument that just returns its parameter (i.e. compactMap { $0 }). Still, for such use cases it would be nice to get rid of the trailing closure.

The implementation isn't as straightforward as your usual extension, but once it has been written, the call site definitely gets cleaner 👌

import Foundation

protocol OptionalConvertible {
    associatedtype Wrapped
    func asOptional() -> Wrapped?
}

extension Optional: OptionalConvertible {
    func asOptional() -> Wrapped? {
        return self
    }
}

extension Sequence where Element: OptionalConvertible {
    func compacted() -> [Element.Wrapped] {
        return compactMap { $0.asOptional() }
    }
}

let data = [nil, 1, 2, nil, 3, 5, nil, 8, nil]
data.compacted() // [1, 2, 3, 5, 8]

Dealing with expirable values

It might happen that your code has to deal with values that come with an expiration date. In a game, it could be a score multiplier that will only last for 30 seconds. Or it could be an authentication token for an API, with a 15 minutes lifespan. In both instances you can rely on the type Expirable to encapsulate the expiration logic.

import Foundation

struct Expirable<T> {
    private var innerValue: T
    private(set) var expirationDate: Date
    
    var value: T? {
        return hasExpired() ? nil : innerValue
    }
    
    init(value: T, expirationDate: Date) {
        self.innerValue = value
        self.expirationDate = expirationDate
    }
    
    init(value: T, duration: Double) {
        self.innerValue = value
        self.expirationDate = Date().addingTimeInterval(duration)
    }
    
    func hasExpired() -> Bool {
        return expirationDate < Date()
    }
}

let expirable = Expirable(value: 42, duration: 3)

sleep(2)
expirable.value // 42
sleep(2)
expirable.value // nil

I share the credit for this tip with Benoît Caron.

Using parallelism to speed-up map()

Almost all Apple devices able to run Swift code are powered by a multi-core CPU, consequently making a good use of parallelism is a great way to improve code performance. map() is a perfect candidate for such an optimization, because it is almost trivial to define a parallel implementation.

import Foundation

extension Array {
    func parallelMap<T>(_ transform: (Element) -> T) -> [T] {
        let res = UnsafeMutablePointer<T>.allocate(capacity: count)
        
        DispatchQueue.concurrentPerform(iterations: count) { i in
            res[i] = transform(self[i])
        }
        
        let finalResult = Array<T>(UnsafeBufferPointer(start: res, count: count))
        res.deallocate(capacity: count)
        
        return finalResult
    }
}

let array = (0..<1_000).map { $0 }

func work(_ n: Int) -> Int {
    return (0..<n).reduce(0, +)
}

array.parallelMap { work($0) }

🚨 Make sure to only use parallelMap() when the transform function actually performs some costly computations. Otherwise performances will be systematically slower than using map(), because of the multithreading overhead.

Measuring execution time with minimum boilerplate

During development of a feature that performs some heavy computations, it can be helpful to measure just how much time a chunk of code takes to run. The time() function is a nice tool for this purpose, because of how simple it is to add and then to remove when it is no longer needed.

import Foundation

func time(averagedExecutions: Int = 1, _ code: () -> Void) {
    let start = Date()
    for _ in 0..<averagedExecutions { code() }
    let end = Date()
    
    let duration = end.timeIntervalSince(start) / Double(averagedExecutions)
    
    print("time: \(duration)")
}

time {
    (0...10_000).map { $0 * $0 }
}
// time: 0.183973908424377

Running two pieces of code in parallel

Concurrency is definitely one of those topics were the right encapsulation bears the potential to make your life so much easier. For instance, with this piece of code you can easily launch two computations in parallel, and have the results returned in a tuple.

import Foundation

func parallel<T, U>(_ left: @autoclosure () -> T, _ right: @autoclosure () -> U) -> (T, U) {
    var leftRes: T?
    var rightRes: U?
    
    DispatchQueue.concurrentPerform(iterations: 2, execute: { id in
        if id == 0 {
            leftRes = left()
        } else {
            rightRes = right()
        }
    })
    
    return (leftRes!, rightRes!)
}

let values = (1...100_000).map { $0 }

let results = parallel(values.map { $0 * $0 }, values.reduce(0, +))

Making good use of #file, #line and #function

Swift exposes three special variables #file, #line and #function, that are respectively set to the name of the current file, line and function. Those variables become very useful when writing custom logging functions or test predicates.

import Foundation

func log(_ message: String, _ file: String = #file, _ line: Int = #line, _ function: String = #function) {
    print("[\(file):\(line)] \(function) - \(message)")
}

func foo() {
    log("Hello world!")
}

foo() // [MyPlayground.playground:8] foo() - Hello world!

Comparing Optionals through Conditional Conformance

Swift 4.1 has introduced a new feature called Conditional Conformance, which allows a type to implement a protocol only when its generic type also does.

With this addition it becomes easy to let Optional implement Comparable only when Wrapped also implements Comparable:

import Foundation

extension Optional: Comparable where Wrapped: Comparable {
    public static func < (lhs: Optional, rhs: Optional) -> Bool {
        switch (lhs, rhs) {
        case let (lhs?, rhs?):
            return lhs < rhs
        case (nil, _?):
            return true // anything is greater than nil
        case (_?, nil):
            return false // nil in smaller than anything
        case (nil, nil):
            return true // nil is not smaller than itself
        }
    }
}

let data: [Int?] = [8, 4, 3, nil, 12, 4, 2, nil, -5]
data.sorted() // [nil, nil, Optional(-5), Optional(2), Optional(3), Optional(4), Optional(4), Optional(8), Optional(12)]

Safely subscripting a Collection

Any attempt to access an Array beyond its bounds will result in a crash. While it's possible to write conditions such as if index < array.count { array[index] } in order to prevent such crashes, this approach will rapidly become cumbersome.

A great thing is that this condition can be encapsulated in a custom subscript that will work on any Collection:

import Foundation

extension Collection {
    subscript (safe index: Index) -> Element? {
        return indices.contains(index) ? self[index] : nil
    }
}

let data = [1, 3, 4]

data[safe: 1] // Optional(3)
data[safe: 10] // nil

Easier String slicing using ranges

Subscripting a string with a range can be very cumbersome in Swift 4. Let's face it, no one wants to write lines like someString[index(startIndex, offsetBy: 0)..<index(startIndex, offsetBy: 10)] on a regular basis.

Luckily, with the addition of one clever extension, strings can be sliced as easily as arrays 🎉

import Foundation

extension String {
    public subscript(value: CountableClosedRange<Int>) -> Substring {
        get {
            return self[index(startIndex, offsetBy: value.lowerBound)...index(startIndex, offsetBy: value.upperBound)]
        }
    }
    
    public subscript(value: CountableRange<Int>) -> Substring {
        get {
            return self[index(startIndex, offsetBy: value.lowerBound)..<index(startIndex, offsetBy: value.upperBound)]
        }
    }
    
    public subscript(value: PartialRangeUpTo<Int>) -> Substring {
        get {
            return self[..<index(startIndex, offsetBy: value.upperBound)]
        }
    }
    
    public subscript(value: PartialRangeThrough<Int>) -> Substring {
        get {
            return self[...index(startIndex, offsetBy: value.upperBound)]
        }
    }
    
    public subscript(value: PartialRangeFrom<Int>) -> Substring {
        get {
            return self[index(startIndex, offsetBy: value.lowerBound)...]
        }
    }
}

let data = "This is a string!"

data[..<4]  // "This"
data[5..<9] // "is a"
data[10...] // "string!"

Concise syntax for sorting using a KeyPath

By using a KeyPath along with a generic type, a very clean and concise syntax for sorting data can be implemented:

import Foundation

extension Sequence {
    func sorted<T: Comparable>(by attribute: KeyPath<Element, T>) -> [Element] {
        return sorted(by: { $0[keyPath: attribute] < $1[keyPath: attribute] })
    }
}

let data = ["Some", "words", "of", "different", "lengths"]

data.sorted(by: \.count) // ["of", "Some", "words", "lengths", "different"]

If you like this syntax, make sure to checkout KeyPathKit!

Manufacturing cache-efficient versions of pure functions

By capturing a local variable in a returned closure, it is possible to manufacture cache-efficient versions of pure functions. Be careful though, this trick only works with non-recursive function!

import Foundation

func cached<In: Hashable, Out>(_ f: @escaping (In) -> Out) -> (In) -> Out {
    var cache = [In: Out]()
    
    return { (input: In) -> Out in
        if let cachedValue = cache[input] {
            return cachedValue
        } else {
            let result = f(input)
            cache[input] = result
            return result
        }
    }
}

let cachedCos = cached { (x: Double) in cos(x) }

cachedCos(.pi * 2) // value of cos for 2π is now cached

Simplifying complex conditions with pattern matching

When distinguishing between complex boolean conditions, using a switch statement along with pattern matching can be more readable than the classic series of if {} else if {}.

import Foundation

let expr1: Bool
let expr2: Bool
let expr3: Bool

if expr1 && !expr3 {
    functionA()
} else if !expr2 && expr3 {
    functionB()
} else if expr1 && !expr2 && expr3 {
    functionC()
}

switch (expr1, expr2, expr3) {
    
case (true, _, false):
    functionA()
case (_, false, true):
    functionB()
case (true, false, true):
    functionC()
default:
    break
}

Easily generating arrays of data

Using map() on a range makes it easy to generate an array of data.

import Foundation

func randomInt() -> Int { return Int(arc4random()) }

let randomArray = (1...10).map { _ in randomInt() }

Using @autoclosure for cleaner call sites

Using @autoclosure enables the compiler to automatically wrap an argument within a closure, thus allowing for a very clean syntax at call sites.

import UIKit

extension UIView {
    class func animate(withDuration duration: TimeInterval, _ animations: @escaping @autoclosure () -> Void) {
        UIView.animate(withDuration: duration, animations: animations)
    }
}

let view = UIView()

UIView.animate(withDuration: 0.3, view.backgroundColor = .orange)

Observing new and old value with RxSwift

When working with RxSwift, it's very easy to observe both the current and previous value of an observable sequence by simply introducing a shift using skip().

import RxSwift

let values = Observable.of(4, 8, 15, 16, 23, 42)

let newAndOld = Observable.zip(values, values.skip(1)) { (previous: $0, current: $1) }
    .subscribe(onNext: { pair in
        print("current: \(pair.current) - previous: \(pair.previous)")
    })

//current: 8 - previous: 4
//current: 15 - previous: 8
//current: 16 - previous: 15
//current: 23 - previous: 16
//current: 42 - previous: 23

Implicit initialization from literal values

Using protocols such as ExpressibleByStringLiteral it is possible to provide an init that will be automatically when a literal value is provided, allowing for nice and short syntax. This can be very helpful when writing mock or test data.

import Foundation

extension URL: ExpressibleByStringLiteral {
    public init(stringLiteral value: String) {
        self.init(string: value)!
    }
}

let url: URL = "http://www.google.fr"

NSURLConnection.canHandle(URLRequest(url: "http://www.google.fr"))

Achieving systematic validation of data

Through some clever use of Swift private visibility it is possible to define a container that holds any untrusted value (such as a user input) from which the only way to retrieve the value is by making it successfully pass a validation test.

import Foundation

struct Untrusted<T> {
    private(set) var value: T
}

protocol Validator {
    associatedtype T
    static func validation(value: T) -> Bool
}

extension Validator {
    static func validate(untrusted: Untrusted<T>) -> T? {
        if self.validation(value: untrusted.value) {
            return untrusted.value
        } else {
            return nil
        }
    }
}

struct FrenchPhoneNumberValidator: Validator {
    static func validation(value: String) -> Bool {
       return (value.count) == 10 && CharacterSet(charactersIn: value).isSubset(of: CharacterSet.decimalDigits)
    }
}

let validInput = Untrusted(value: "0122334455")
let invalidInput = Untrusted(value: "0123")

FrenchPhoneNumberValidator.validate(untrusted: validInput) // returns "0122334455"
FrenchPhoneNumberValidator.validate(untrusted: invalidInput) // returns nil

Implementing the builder pattern with keypaths

With the addition of keypaths in Swift 4, it is now possible to easily implement the builder pattern, that allows the developer to clearly separate the code that initializes a value from the code that uses it, without the burden of defining a factory method.

import UIKit

protocol With {}

extension With where Self: AnyObject {
    @discardableResult
    func with<T>(_ property: ReferenceWritableKeyPath<Self, T>, setTo value: T) -> Self {
        self[keyPath: property] = value
        return self
    }
}

extension UIView: With {}

let view = UIView()

let label = UILabel()
    .with(\.textColor, setTo: .red)
    .with(\.text, setTo: "Foo")
    .with(\.textAlignment, setTo: .right)
    .with(\.layer.cornerRadius, setTo: 5)

view.addSubview(label)

🚨 The Swift compiler does not perform OS availability checks on properties referenced by keypaths. Any attempt to use a KeyPath for an unavailable property will result in a runtime crash.

I share the credit for this tip with Marion Curtil.

Storing functions rather than values

When a type stores values for the sole purpose of parametrizing its functions, it’s then possible to not store the values but directly the function, with no discernable difference at the call site.

import Foundation

struct MaxValidator {
    let max: Int
    let strictComparison: Bool
    
    func isValid(_ value: Int) -> Bool {
        return self.strictComparison ? value < self.max : value <= self.max
    }
}

struct MaxValidator2 {
    var isValid: (_ value: Int) -> Bool
    
    init(max: Int, strictComparison: Bool) {
        self.isValid = strictComparison ? { $0 < max } : { $0 <= max }
    }
}

MaxValidator(max: 5, strictComparison: true).isValid(5) // false
MaxValidator2(max: 5, strictComparison: false).isValid(5) // true

Defining operators on function types

Functions are first-class citizen types in Swift, so it is perfectly legal to define operators for them.

import Foundation

let firstRange = { (0...3).contains($0) }
let secondRange = { (5...6).contains($0) }

func ||(_ lhs: @escaping (Int) -> Bool, _ rhs: @escaping (Int) -> Bool) -> (Int) -> Bool {
    return { value in
        return lhs(value) || rhs(value)
    }
}

(firstRange || secondRange)(2) // true
(firstRange || secondRange)(4) // false
(firstRange || secondRange)(6) // true

Typealiases for functions

Typealiases are great to express function signatures in a more comprehensive manner, which then enables us to easily define functions that operate on them, resulting in a nice way to write and use some powerful API.

import Foundation

typealias RangeSet = (Int) -> Bool

func union(_ left: @escaping RangeSet, _ right: @escaping RangeSet) -> RangeSet {
    return { left($0) || right($0) }
}

let firstRange = { (0...3).contains($0) }
let secondRange = { (5...6).contains($0) }

let unionRange = union(firstRange, secondRange)

unionRange(2) // true
unionRange(4) // false

Encapsulating state within a function

By returning a closure that captures a local variable, it's possible to encapsulate a mutable state within a function.

import Foundation

func counterFactory() -> () -> Int {
    var counter = 0
    
    return {
        counter += 1
        return counter
    }
}

let counter = counterFactory()

counter() // returns 1
counter() // returns 2

Generating all cases for an Enum

⚠️ Since Swift 4.2, allCases can now be synthesized at compile-time by simply conforming to the protocol CaseIterable. The implementation below should no longer be used in production code.

Through some clever leveraging of how enums are stored in memory, it is possible to generate an array that contains all the possible cases of an enum. This can prove particularly useful when writing unit tests that consume random data.

import Foundation

enum MyEnum { case first; case second; case third; case fourth }

protocol EnumCollection: Hashable {
    static var allCases: [Self] { get }
}

extension EnumCollection {
    public static var allCases: [Self] {
        var i = 0
        return Array(AnyIterator {
            let next = withUnsafePointer(to: &i) {
                $0.withMemoryRebound(to: Self.self, capacity: 1) { $0.pointee }
            }
            if next.hashValue != i { return nil }
            i += 1
            return next
        })
    }
}

extension MyEnum: EnumCollection { }

MyEnum.allCases // [.first, .second, .third, .fourth]

Using map on optional values

The if-let syntax is a great way to deal with optional values in a safe manner, but at times it can prove to be just a little bit to cumbersome. In such cases, using the Optional.map() function is a nice way to achieve a shorter code while retaining safeness and readability.

import UIKit

let date: Date? = Date() // or could be nil, doesn't matter
let formatter = DateFormatter()
let label = UILabel()

if let safeDate = date {
    label.text = formatter.string(from: safeDate)
}

label.text = date.map { return formatter.string(from: $0) }

label.text = date.map(formatter.string(from:)) // even shorter, tough less readable

📣 NEW 📣 Swift Tips are now available on YouTube 👇

Summary

Tips


Download Details:

Author: vincent-pradeilles
Source code: https://github.com/vincent-pradeilles/swift-tips

License: MIT license
#swift 

Swift Tips: A Collection Useful Tips for The Swift Language
Daron  Moore

Daron Moore

1661575685

Linkedin: LinkedIn's Official Swift Style Guide

Swift Style Guide

Make sure to read Apple's API Design Guidelines.

Specifics from these guidelines + additional remarks are mentioned below.

This guide was last updated for Swift 4.0 on February 14, 2018.

1. Code Formatting

  • 1.1 Use 4 spaces for tabs.
  • 1.2 Avoid uncomfortably long lines with a hard maximum of 160 characters per line (Xcode->Preferences->Text Editing->Page guide at column: 160 is helpful for this)
  • 1.3 Ensure that there is a newline at the end of every file.
  • 1.4 Ensure that there is no trailing whitespace anywhere (Xcode->Preferences->Text Editing->Automatically trim trailing whitespace + Including whitespace-only lines).
  • 1.5 Do not place opening braces on new lines - we use the 1TBS style.
class SomeClass {
    func someMethod() {
        if x == y {
            /* ... */
        } else if x == z {
            /* ... */
        } else {
            /* ... */
        }
    }

    /* ... */
}
  • 1.6 When writing a type for a property, constant, variable, a key for a dictionary, a function argument, a protocol conformance, or a superclass, don't add a space before the colon.
// specifying type
let pirateViewController: PirateViewController

// dictionary syntax (note that we left-align as opposed to aligning colons)
let ninjaDictionary: [String: AnyObject] = [
    "fightLikeDairyFarmer": false,
    "disgusting": true
]

// declaring a function
func myFunction<T, U: SomeProtocol>(firstArgument: U, secondArgument: T) where T.RelatedType == U {
    /* ... */
}

// calling a function
someFunction(someArgument: "Kitten")

// superclasses
class PirateViewController: UIViewController {
    /* ... */
}

// protocols
extension PirateViewController: UITableViewDataSource {
    /* ... */
}
  • 1.7 In general, there should be a space following a comma.
let myArray = [1, 2, 3, 4, 5]
  • 1.8 There should be a space before and after a binary operator such as +, ==, or ->. There should also not be a space after a ( and before a ).
let myValue = 20 + (30 / 2) * 3
if 1 + 1 == 3 {
    fatalError("The universe is broken.")
}
func pancake(with syrup: Syrup) -> Pancake {
    /* ... */
}
  • 1.9 We follow Xcode's recommended indentation style (i.e. your code should not change if CTRL-I is pressed). When declaring a function that spans multiple lines, prefer using that syntax to which Xcode, as of version 7.3, defaults.
// Xcode indentation for a function declaration that spans multiple lines
func myFunctionWithManyParameters(parameterOne: String,
                                  parameterTwo: String,
                                  parameterThree: String) {
    // Xcode indents to here for this kind of statement
    print("\(parameterOne) \(parameterTwo) \(parameterThree)")
}

// Xcode indentation for a multi-line `if` statement
if myFirstValue > (mySecondValue + myThirdValue)
    && myFourthValue == .someEnumValue {

    // Xcode indents to here for this kind of statement
    print("Hello, World!")
}
  • 1.10 When calling a function that has many parameters, put each argument on a separate line with a single extra indentation.
someFunctionWithManyArguments(
    firstArgument: "Hello, I am a string",
    secondArgument: resultFromSomeFunction(),
    thirdArgument: someOtherLocalProperty)
  • 1.11 When dealing with an implicit array or dictionary large enough to warrant splitting it into multiple lines, treat the [ and ] as if they were braces in a method, if statement, etc. Closures in a method should be treated similarly.
someFunctionWithABunchOfArguments(
    someStringArgument: "hello I am a string",
    someArrayArgument: [
        "dadada daaaa daaaa dadada daaaa daaaa dadada daaaa daaaa",
        "string one is crazy - what is it thinking?"
    ],
    someDictionaryArgument: [
        "dictionary key 1": "some value 1, but also some more text here",
        "dictionary key 2": "some value 2"
    ],
    someClosure: { parameter1 in
        print(parameter1)
    })
  • 1.12 Prefer using local constants or other mitigation techniques to avoid multi-line predicates where possible.
// PREFERRED
let firstCondition = x == firstReallyReallyLongPredicateFunction()
let secondCondition = y == secondReallyReallyLongPredicateFunction()
let thirdCondition = z == thirdReallyReallyLongPredicateFunction()
if firstCondition && secondCondition && thirdCondition {
    // do something
}

// NOT PREFERRED
if x == firstReallyReallyLongPredicateFunction()
    && y == secondReallyReallyLongPredicateFunction()
    && z == thirdReallyReallyLongPredicateFunction() {
    // do something
}

2. Naming

2.1 There is no need for Objective-C style prefixing in Swift (e.g. use just GuybrushThreepwood instead of LIGuybrushThreepwood).

2.2 Use PascalCase for type names (e.g. struct, enum, class, typedef, associatedtype, etc.).

2.3 Use camelCase (initial lowercase letter) for function, method, property, constant, variable, argument names, enum cases, etc.

2.4 When dealing with an acronym or other name that is usually written in all caps, actually use all caps in any names that use this in code. The exception is if this word is at the start of a name that needs to start with lowercase - in this case, use all lowercase for the acronym.

// "HTML" is at the start of a constant name, so we use lowercase "html"
let htmlBodyContent: String = "<p>Hello, World!</p>"
// Prefer using ID to Id
let profileID: Int = 1
// Prefer URLFinder to UrlFinder
class URLFinder {
    /* ... */
}
  • 2.5 All constants that are instance-independent should be static. All such static constants should be placed in a marked section of their class, struct, or enum. For classes with many constants, you should group constants that have similar or the same prefixes, suffixes and/or use cases.
// PREFERRED    
class MyClassName {
    // MARK: - Constants
    static let buttonPadding: CGFloat = 20.0
    static let indianaPi = 3
    static let shared = MyClassName()
}

// NOT PREFERRED
class MyClassName {
    // Don't use `k`-prefix
    static let kButtonPadding: CGFloat = 20.0

    // Don't namespace constants
    enum Constant {
        static let indianaPi = 3
    }
}
  • 2.6 For generics and associated types, use a PascalCase word that describes the generic. If this word clashes with a protocol that it conforms to or a superclass that it subclasses, you can append a Type suffix to the associated type or generic name.
class SomeClass<Model> { /* ... */ }
protocol Modelable {
    associatedtype Model
}
protocol Sequence {
    associatedtype IteratorType: Iterator
}
  • 2.7 Names should be descriptive and unambiguous.
// PREFERRED
class RoundAnimatingButton: UIButton { /* ... */ }

// NOT PREFERRED
class CustomButton: UIButton { /* ... */ }
  • 2.8 Do not abbreviate, use shortened names, or single letter names.
// PREFERRED
class RoundAnimatingButton: UIButton {
    let animationDuration: NSTimeInterval

    func startAnimating() {
        let firstSubview = subviews.first
    }

}

// NOT PREFERRED
class RoundAnimating: UIButton {
    let aniDur: NSTimeInterval

    func srtAnmating() {
        let v = subviews.first
    }
}
  • 2.9 Include type information in constant or variable names when it is not obvious otherwise.
// PREFERRED
class ConnectionTableViewCell: UITableViewCell {
    let personImageView: UIImageView

    let animationDuration: TimeInterval

    // it is ok not to include string in the ivar name here because it's obvious
    // that it's a string from the property name
    let firstName: String

    // though not preferred, it is OK to use `Controller` instead of `ViewController`
    let popupController: UIViewController
    let popupViewController: UIViewController

    // when working with a subclass of `UIViewController` such as a table view
    // controller, collection view controller, split view controller, etc.,
    // fully indicate the type in the name.
    let popupTableViewController: UITableViewController

    // when working with outlets, make sure to specify the outlet type in the
    // property name.
    @IBOutlet weak var submitButton: UIButton!
    @IBOutlet weak var emailTextField: UITextField!
    @IBOutlet weak var nameLabel: UILabel!

}

// NOT PREFERRED
class ConnectionTableViewCell: UITableViewCell {
    // this isn't a `UIImage`, so shouldn't be called image
    // use personImageView instead
    let personImage: UIImageView

    // this isn't a `String`, so it should be `textLabel`
    let text: UILabel

    // `animation` is not clearly a time interval
    // use `animationDuration` or `animationTimeInterval` instead
    let animation: TimeInterval

    // this is not obviously a `String`
    // use `transitionText` or `transitionString` instead
    let transition: String

    // this is a view controller - not a view
    let popupView: UIViewController

    // as mentioned previously, we don't want to use abbreviations, so don't use
    // `VC` instead of `ViewController`
    let popupVC: UIViewController

    // even though this is still technically a `UIViewController`, this property
    // should indicate that we are working with a *Table* View Controller
    let popupViewController: UITableViewController

    // for the sake of consistency, we should put the type name at the end of the
    // property name and not at the start
    @IBOutlet weak var btnSubmit: UIButton!
    @IBOutlet weak var buttonSubmit: UIButton!

    // we should always have a type in the property name when dealing with outlets
    // for example, here, we should have `firstNameLabel` instead
    @IBOutlet weak var firstName: UILabel!
}

2.10 When naming function arguments, make sure that the function can be read easily to understand the purpose of each argument.

2.11 As per Apple's API Design Guidelines, a protocol should be named as nouns if they describe what something is doing (e.g. Collection) and using the suffixes able, ible, or ing if it describes a capability (e.g. Equatable, ProgressReporting). If neither of those options makes sense for your use case, you can add a Protocol suffix to the protocol's name as well. Some example protocols are below.

// here, the name is a noun that describes what the protocol does
protocol TableViewSectionProvider {
    func rowHeight(at row: Int) -> CGFloat
    var numberOfRows: Int { get }
    /* ... */
}

// here, the protocol is a capability, and we name it appropriately
protocol Loggable {
    func logCurrentState()
    /* ... */
}

// suppose we have an `InputTextView` class, but we also want a protocol
// to generalize some of the functionality - it might be appropriate to
// use the `Protocol` suffix here
protocol InputTextViewProtocol {
    func sendTrackingEvent()
    func inputText() -> String
    /* ... */
}

3. Coding Style

3.1 General

3.1.1 Prefer let to var whenever possible.

3.1.2 Prefer the composition of map, filter, reduce, etc. over iterating when transforming from one collection to another. Make sure to avoid using closures that have side effects when using these methods.

// PREFERRED
let stringOfInts = [1, 2, 3].flatMap { String($0) }
// ["1", "2", "3"]

// NOT PREFERRED
var stringOfInts: [String] = []
for integer in [1, 2, 3] {
    stringOfInts.append(String(integer))
}

// PREFERRED
let evenNumbers = [4, 8, 15, 16, 23, 42].filter { $0 % 2 == 0 }
// [4, 8, 16, 42]

// NOT PREFERRED
var evenNumbers: [Int] = []
for integer in [4, 8, 15, 16, 23, 42] {
    if integer % 2 == 0 {
        evenNumbers.append(integer)
    }
}

3.1.3 Prefer not declaring types for constants or variables if they can be inferred anyway.

3.1.4 If a function returns multiple values, prefer returning a tuple to using inout arguments (it’s best to use labeled tuples for clarity on what you’re returning if it is not otherwise obvious). If you use a certain tuple more than once, consider using a typealias. If you’re returning 3 or more items in a tuple, consider using a struct or class instead.

func pirateName() -> (firstName: String, lastName: String) {
    return ("Guybrush", "Threepwood")
}

let name = pirateName()
let firstName = name.firstName
let lastName = name.lastName

3.1.5 Be wary of retain cycles when creating delegates/protocols for your classes; typically, these properties should be declared weak.

3.1.6 Be careful when calling self directly from an escaping closure as this can cause a retain cycle - use a capture list when this might be the case:

myFunctionWithEscapingClosure() { [weak self] (error) -> Void in
    // you can do this

    self?.doSomething()

    // or you can do this

    guard let strongSelf = self else {
        return
    }

    strongSelf.doSomething()
}

3.1.7 Don't use labeled breaks.

3.1.8 Don't place parentheses around control flow predicates.

// PREFERRED
if x == y {
    /* ... */
}

// NOT PREFERRED
if (x == y) {
    /* ... */
}
  • 3.1.9 Avoid writing out an enum type where possible - use shorthand.
// PREFERRED
imageView.setImageWithURL(url, type: .person)

// NOT PREFERRED
imageView.setImageWithURL(url, type: AsyncImageView.Type.person)
  • 3.1.10 Don’t use shorthand for class methods since it is generally more difficult to infer the context from class methods as opposed to enums.
// PREFERRED
imageView.backgroundColor = UIColor.white

// NOT PREFERRED
imageView.backgroundColor = .white

3.1.11 Prefer not writing self. unless it is required.

3.1.12 When writing methods, keep in mind whether the method is intended to be overridden or not. If not, mark it as final, though keep in mind that this will prevent the method from being overwritten for testing purposes. In general, final methods result in improved compilation times, so it is good to use this when applicable. Be particularly careful, however, when applying the final keyword in a library since it is non-trivial to change something to be non-final in a library as opposed to have changing something to be non-final in your local project.

3.1.13 When using a statement such as else, catch, etc. that follows a block, put this keyword on the same line as the block. Again, we are following the 1TBS style here. Example if/else and do/catch code is below.

if someBoolean {
    // do something
} else {
    // do something else
}

do {
    let fileContents = try readFile("filename.txt")
} catch {
    print(error)
}

3.1.14 Prefer static to class when declaring a function or property that is associated with a class as opposed to an instance of that class. Only use class if you specifically need the functionality of overriding that function or property in a subclass, though consider using a protocol to achieve this instead.

3.1.15 If you have a function that takes no arguments, has no side effects, and returns some object or value, prefer using a computed property instead.

3.2 Access Modifiers

  • 3.2.1 Write the access modifier keyword first if it is needed.
// PREFERRED
private static let myPrivateNumber: Int

// NOT PREFERRED
static private let myPrivateNumber: Int
  • 3.2.2 The access modifier keyword should not be on a line by itself - keep it inline with what it is describing.
// PREFERRED
open class Pirate {
    /* ... */
}

// NOT PREFERRED
open
class Pirate {
    /* ... */
}

3.2.3 In general, do not write the internal access modifier keyword since it is the default.

3.2.4 If a property needs to be accessed by unit tests, you will have to make it internal to use @testable import ModuleName. If a property should be private, but you declare it to be internal for the purposes of unit testing, make sure you add an appropriate bit of documentation commenting that explains this. You can make use of the - warning: markup syntax for clarity as shown below.

/**
 This property defines the pirate's name.
 - warning: Not `private` for `@testable`.
 */
let pirateName = "LeChuck"

3.2.5 Prefer private to fileprivate where possible.

3.2.6 When choosing between public and open, prefer open if you intend for something to be subclassable outside of a given module and public otherwise. Note that anything internal and above can be subclassed in tests by using @testable import, so this shouldn't be a reason to use open. In general, lean towards being a bit more liberal with using open when it comes to libraries, but a bit more conservative when it comes to modules in a codebase such as an app where it is easy to change things in multiple modules simultaneously.

3.3 Custom Operators

Prefer creating named functions to custom operators.

If you want to introduce a custom operator, make sure that you have a very good reason why you want to introduce a new operator into global scope as opposed to using some other construct.

You can override existing operators to support new types (especially ==). However, your new definitions must preserve the semantics of the operator. For example, == must always test equality and return a boolean.

3.4 Switch Statements and enums

3.4.1 When using a switch statement that has a finite set of possibilities (enum), do NOT include a default case. Instead, place unused cases at the bottom and use the break keyword to prevent execution.

3.4.2 Since switch cases in Swift break by default, do not include the break keyword if it is not needed.

3.4.3 The case statements should line up with the switch statement itself as per default Swift standards.

3.4.4 When defining a case that has an associated value, make sure that this value is appropriately labeled as opposed to just types (e.g. case hunger(hungerLevel: Int) instead of case hunger(Int)).

enum Problem {
    case attitude
    case hair
    case hunger(hungerLevel: Int)
}

func handleProblem(problem: Problem) {
    switch problem {
    case .attitude:
        print("At least I don't have a hair problem.")
    case .hair:
        print("Your barber didn't know when to stop.")
    case .hunger(let hungerLevel):
        print("The hunger level is \(hungerLevel).")
    }
}

3.4.5 Prefer lists of possibilities (e.g. case 1, 2, 3:) to using the fallthrough keyword where possible).

3.4.6 If you have a default case that shouldn't be reached, preferably throw an error (or handle it some other similar way such as asserting).

func handleDigit(_ digit: Int) throws {
    switch digit {
    case 0, 1, 2, 3, 4, 5, 6, 7, 8, 9:
        print("Yes, \(digit) is a digit!")
    default:
        throw Error(message: "The given number was not a digit.")
    }
}

3.5 Optionals

3.5.1 The only time you should be using implicitly unwrapped optionals is with @IBOutlets. In every other case, it is better to use a non-optional or regular optional property. Yes, there are cases in which you can probably "guarantee" that the property will never be nil when used, but it is better to be safe and consistent. Similarly, don't use force unwraps.

3.5.2 Don't use as! or try!.

3.5.3 If you don't plan on actually using the value stored in an optional, but need to determine whether or not this value is nil, explicitly check this value against nil as opposed to using if let syntax.

// PREFERRED
if someOptional != nil {
    // do something
}

// NOT PREFERRED
if let _ = someOptional {
    // do something
}
  • 3.5.4 Don't use unowned. You can think of unowned as somewhat of an equivalent of a weak property that is implicitly unwrapped (though unowned has slight performance improvements on account of completely ignoring reference counting). Since we don't ever want to have implicit unwraps, we similarly don't want unowned properties.
// PREFERRED
weak var parentViewController: UIViewController?

// NOT PREFERRED
weak var parentViewController: UIViewController!
unowned var parentViewController: UIViewController
  • 3.5.5 When unwrapping optionals, use the same name for the unwrapped constant or variable where appropriate.
guard let myValue = myValue else {
    return
}
  • 3.5.6 Use XCTUnwrap instead of forced unwrapping in tests. ```swift func isEvenNumber(_ number: Int) -> Bool { return number % 2 == 0 }

// PREFERRED func testWithXCTUnwrap() throws { let number: Int? = functionThatReturnsOptionalNumber() XCTAssertTrue(isEvenNumber(try XCTUnwrap(number))) }

// NOT PREFERRED func testWithForcedUnwrap() { let number: Int? = functionThatReturnsOptionalNumber() XCTAssertTrue(isEvenNumber(number!)) // may crash the simulator }


### 3.6 Protocols

When implementing protocols, there are two ways of organizing your code:

1. Using `// MARK:` comments to separate your protocol implementation from the rest of your code
2. Using an extension outside your `class`/`struct` implementation code, but in the same source file

Keep in mind that when using an extension, however, the methods in the extension can't be overridden by a subclass, which can make testing difficult. If this is a common use case, it might be better to stick with method #1 for consistency. Otherwise, method #2 allows for cleaner separation of concerns.

Even when using method #2, add `// MARK:` statements anyway for easier readability in Xcode's method/property/class/etc. list UI.

### 3.7 Properties

* **3.7.1** If making a read-only, computed property, provide the getter without the `get {}` around it.

```swift
var computedProperty: String {
    if someBool {
        return "I'm a mighty pirate!"
    }
    return "I'm selling these fine leather jackets."
}
  • 3.7.2 When using get {}, set {}, willSet, and didSet, indent these blocks.
  • 3.7.3 Though you can create a custom name for the new or old value for willSet/didSet and set, use the standard newValue/oldValue identifiers that are provided by default.
var storedProperty: String = "I'm selling these fine leather jackets." {
    willSet {
        print("will set to \(newValue)")
    }
    didSet {
        print("did set from \(oldValue) to \(storedProperty)")
    }
}

var computedProperty: String  {
    get {
        if someBool {
            return "I'm a mighty pirate!"
        }
        return storedProperty
    }
    set {
        storedProperty = newValue
    }
}
  • 3.7.4 You can declare a singleton property as follows:
class PirateManager {
    static let shared = PirateManager()

    /* ... */
}

3.8 Closures

  • 3.8.1 If the types of the parameters are obvious, it is OK to omit the type name, but being explicit is also OK. Sometimes readability is enhanced by adding clarifying detail and sometimes by taking repetitive parts away - use your best judgment and be consistent.
// omitting the type
doSomethingWithClosure() { response in
    print(response)
}

// explicit type
doSomethingWithClosure() { response: NSURLResponse in
    print(response)
}

// using shorthand in a map statement
[1, 2, 3].flatMap { String($0) }
  • 3.8.2 If specifying a closure as a type, you don’t need to wrap it in parentheses unless it is required (e.g. if the type is optional or the closure is within another closure). Always wrap the arguments in the closure in a set of parentheses - use () to indicate no arguments and use Void to indicate that nothing is returned.
let completionBlock: (Bool) -> Void = { (success) in
    print("Success? \(success)")
}

let completionBlock: () -> Void = {
    print("Completed!")
}

let completionBlock: (() -> Void)? = nil

3.8.3 Keep parameter names on same line as the opening brace for closures when possible without too much horizontal overflow (i.e. ensure lines are less than 160 characters).

3.8.4 Use trailing closure syntax unless the meaning of the closure is not obvious without the parameter name (an example of this could be if a method has parameters for success and failure closures).

// trailing closure
doSomething(1.0) { (parameter1) in
    print("Parameter 1 is \(parameter1)")
}

// no trailing closure
doSomething(1.0, success: { (parameter1) in
    print("Success with \(parameter1)")
}, failure: { (parameter1) in
    print("Failure with \(parameter1)")
})

3.9 Arrays

3.9.1 In general, avoid accessing an array directly with subscripts. When possible, use accessors such as .first or .last, which are optional and won’t crash. Prefer using a for item in items syntax when possible as opposed to something like for i in 0 ..< items.count. If you need to access an array subscript directly, make sure to do proper bounds checking. You can use for (index, value) in items.enumerated() to get both the index and the value.

3.9.2 Never use the += or + operator to append/concatenate to arrays. Instead, use .append() or .append(contentsOf:) as these are far more performant (at least with respect to compilation) in Swift's current state. If you are declaring an array that is based on other arrays and want to keep it immutable, instead of let myNewArray = arr1 + arr2, use let myNewArray = [arr1, arr2].joined().

3.10 Error Handling

Suppose a function myFunction is supposed to return a String, however, at some point it can run into an error. A common approach is to have this function return an optional String? where we return nil if something went wrong.

Example:

func readFile(named filename: String) -> String? {
    guard let file = openFile(named: filename) else {
        return nil
    }

    let fileContents = file.read()
    file.close()
    return fileContents
}

func printSomeFile() {
    let filename = "somefile.txt"
    guard let fileContents = readFile(named: filename) else {
        print("Unable to open file \(filename).")
        return
    }
    print(fileContents)
}

Instead, we should be using Swift's try/catch behavior when it is appropriate to know the reason for the failure.

You can use a struct such as the following:

struct Error: Swift.Error {
    public let file: StaticString
    public let function: StaticString
    public let line: UInt
    public let message: String

    public init(message: String, file: StaticString = #file, function: StaticString = #function, line: UInt = #line) {
        self.file = file
        self.function = function
        self.line = line
        self.message = message
    }
}

Example usage:

func readFile(named filename: String) throws -> String {
    guard let file = openFile(named: filename) else {
        throw Error(message: "Unable to open file named \(filename).")
    }

    let fileContents = file.read()
    file.close()
    return fileContents
}

func printSomeFile() {
    do {
        let fileContents = try readFile(named: filename)
        print(fileContents)
    } catch {
        print(error)
    }
}

There are some exceptions in which it does make sense to use an optional as opposed to error handling. When the result should semantically potentially be nil as opposed to something going wrong while retrieving the result, it makes sense to return an optional instead of using error handling.

In general, if a method can "fail", and the reason for the failure is not immediately obvious if using an optional return type, it probably makes sense for the method to throw an error.

3.11 Using guard Statements

  • 3.11.1 In general, we prefer to use an "early return" strategy where applicable as opposed to nesting code in if statements. Using guard statements for this use-case is often helpful and can improve the readability of the code.
// PREFERRED
func eatDoughnut(at index: Int) {
    guard index >= 0 && index < doughnuts.count else {
        // return early because the index is out of bounds
        return
    }

    let doughnut = doughnuts[index]
    eat(doughnut)
}

// NOT PREFERRED
func eatDoughnut(at index: Int) {
    if index >= 0 && index < doughnuts.count {
        let doughnut = doughnuts[index]
        eat(doughnut)
    }
}
  • 3.11.2 When unwrapping optionals, prefer guard statements as opposed to if statements to decrease the amount of nested indentation in your code.
// PREFERRED
guard let monkeyIsland = monkeyIsland else {
    return
}
bookVacation(on: monkeyIsland)
bragAboutVacation(at: monkeyIsland)

// NOT PREFERRED
if let monkeyIsland = monkeyIsland {
    bookVacation(on: monkeyIsland)
    bragAboutVacation(at: monkeyIsland)
}

// EVEN LESS PREFERRED
if monkeyIsland == nil {
    return
}
bookVacation(on: monkeyIsland!)
bragAboutVacation(at: monkeyIsland!)
  • 3.11.3 When deciding between using an if statement or a guard statement when unwrapping optionals is not involved, the most important thing to keep in mind is the readability of the code. There are many possible cases here, such as depending on two different booleans, a complicated logical statement involving multiple comparisons, etc., so in general, use your best judgement to write code that is readable and consistent. If you are unsure whether guard or if is more readable or they seem equally readable, prefer using guard.
// an `if` statement is readable here
if operationFailed {
    return
}

// a `guard` statement is readable here
guard isSuccessful else {
    return
}

// double negative logic like this can get hard to read - i.e. don't do this
guard !operationFailed else {
    return
}
  • 3.11.4 If choosing between two different states, it makes more sense to use an if statement as opposed to a guard statement.
// PREFERRED
if isFriendly {
    print("Hello, nice to meet you!")
} else {
    print("You have the manners of a beggar.")
}

// NOT PREFERRED
guard isFriendly else {
    print("You have the manners of a beggar.")
    return
}

print("Hello, nice to meet you!")
  • 3.11.5 You should also use guard only if a failure should result in exiting the current context. Below is an example in which it makes more sense to use two if statements instead of using two guards - we have two unrelated conditions that should not block one another.
if let monkeyIsland = monkeyIsland {
    bookVacation(onIsland: monkeyIsland)
}

if let woodchuck = woodchuck, canChuckWood(woodchuck) {
    woodchuck.chuckWood()
}
  • 3.11.6 Often, we can run into a situation in which we need to unwrap multiple optionals using guard statements. In general, combine unwraps into a single guard statement if handling the failure of each unwrap is identical (e.g. just a return, break, continue, throw, or some other @noescape).
// combined because we just return
guard let thingOne = thingOne,
    let thingTwo = thingTwo,
    let thingThree = thingThree else {
    return
}

// separate statements because we handle a specific error in each case
guard let thingOne = thingOne else {
    throw Error(message: "Unwrapping thingOne failed.")
}

guard let thingTwo = thingTwo else {
    throw Error(message: "Unwrapping thingTwo failed.")
}

guard let thingThree = thingThree else {
    throw Error(message: "Unwrapping thingThree failed.")
}
  • 3.11.7 Don’t use one-liners for guard statements.
// PREFERRED
guard let thingOne = thingOne else {
    return
}

// NOT PREFERRED
guard let thingOne = thingOne else { return }

4. Documentation/Comments

4.1 Documentation

If a function is more complicated than a simple O(1) operation, you should generally consider adding a doc comment for the function since there could be some information that the method signature does not make immediately obvious. If there are any quirks to the way that something was implemented, whether technically interesting, tricky, not obvious, etc., this should be documented. Documentation should be added for complex classes/structs/enums/protocols and properties. All public functions/classes/properties/constants/structs/enums/protocols/etc. should be documented as well (provided, again, that their signature/name does not make their meaning/functionality immediately obvious).

After writing a doc comment, you should option click the function/property/class/etc. to make sure that everything is formatted correctly.

Be sure to check out the full set of features available in Swift's comment markup described in Apple's Documentation.

Guidelines:

4.1.1 160 character column limit (like the rest of the code).

4.1.2 Even if the doc comment takes up one line, use block (/** */).

4.1.3 Do not prefix each additional line with a *.

4.1.4 Use the new - parameter syntax as opposed to the old :param: syntax (make sure to use lower case parameter and not Parameter). Option-click on a method you wrote to make sure the quick help looks correct.

class Human {
    /**
     This method feeds a certain food to a person.

     - parameter food: The food you want to be eaten.
     - parameter person: The person who should eat the food.
     - returns: True if the food was eaten by the person; false otherwise.
    */
    func feed(_ food: Food, to person: Human) -> Bool {
        // ...
    }
}

4.1.5 If you’re going to be documenting the parameters/returns/throws of a method, document all of them, even if some of the documentation ends up being somewhat repetitive (this is preferable to having the documentation look incomplete). Sometimes, if only a single parameter warrants documentation, it might be better to just mention it in the description instead.

4.1.6 For complicated classes, describe the usage of the class with some potential examples as seems appropriate. Remember that markdown syntax is valid in Swift's comment docs. Newlines, lists, etc. are therefore appropriate.

/**
 ## Feature Support

 This class does some awesome things. It supports:

 - Feature 1
 - Feature 2
 - Feature 3

 ## Examples

 Here is an example use case indented by four spaces because that indicates a
 code block:

     let myAwesomeThing = MyAwesomeClass()
     myAwesomeThing.makeMoney()

 ## Warnings

 There are some things you should be careful of:

 1. Thing one
 2. Thing two
 3. Thing three
 */
class MyAwesomeClass {
    /* ... */
}
  • 4.1.7 When mentioning code, use code ticks - `
/**
 This does something with a `UIViewController`, perchance.
 - warning: Make sure that `someValue` is `true` before running this function.
 */
func myFunction() {
    /* ... */
}
  • 4.1.8 When writing doc comments, prefer brevity where possible.

4.2 Other Commenting Guidelines

  • 4.2.1 Always leave a space after //.
  • 4.2.2 Always leave comments on their own line.
  • 4.2.3 When using // MARK: - whatever, leave a newline after the comment.
class Pirate {

    // MARK: - instance properties

    private let pirateName: String

    // MARK: - initialization

    init() {
        /* ... */
    }

}

Download Details:

Author: linkedin
Source code: https://github.com/linkedin/swift-style-guide

License:   View license
#swift 

Linkedin: LinkedIn's Official Swift Style Guide
Nat  Grady

Nat Grady

1661041080

R Studio Add in to Quickly Grab Default Function Arguments

getfunctionargs

Introduction

This is a basic package which provides one function, and add in for R Studio called get_fn_args. This provides an add in option for R Studio, which, when highlighting code, will pick out individual arguments and read them to the console.

The main use case for this is when you have a function with a number of default arguments you want to read in, as in the example in the image below.

We can see that this function has read it in.

You can also call the function directly with get_fn_args("x = 4, y = 7, z = 3")

Installation

Use

devtools::install_git(
  url = "https://github.com/kieranjmartin/getfunctionargs.git",
)

Then in R Studio you can load it as usual or find it on the add in menu

Adding hot keys

It can be annoying to go to the menu, so you can assign a hot key to the command, as in these screenshots.

Download Details:

Author: Kieranjmartin
Source Code: https://github.com/kieranjmartin/getfunctionargs 

#r #function #arguments 

R Studio Add in to Quickly Grab Default Function Arguments
Nat  Grady

Nat Grady

1660990920

R Function & Addin to Easily insert Tables In Rmd Code Chunks

inserttable

inserttable is an RStudio add-in facilitating insertion of nicely formatted tables in R markdown documents or plain R scripts.

Installation

You can install inserttable from GitHub with:

# install.packages("devtools")
devtools::install_github("lbusett/insert_table")

Usage

Upon installing, inserttable registers a new RStudio Addin (Insert Table) that can be used to easily insert a table in a Rmd document. To use it, open a Rmd or R document and select “Addins –> Insert Table”.

There are two main use modes:

Launch the addin with the cursor on a empty line

In this case, a GUI will open allowing you to select the desired output format ( kable, kableExtra, DT and rhandsontable are currently implemented), and to edit the content of the table. After clicking Done the Addin will add in the file the code needed to generate the table in a nice tribble format (thanks to Miles McBain’s datapasta package!) to allow easier additional editing, and also the code needed to render it with the selected output format using some default options, as can be seen below:

IMPORTANT NOTE: Not all output formats play well with knitting to PDF or Word!. kable works everywhere, while DT and rhandsontable work out of the box only if knitting to html. You can make them work on PDF and Word by adding always_allow_html: yes in the yaml header of the Rmd, and installing phantomjs using: webshot::install_phantomjs() (results are not that good, though).

animation_1.gif

A useful feature is that, for larger tables, you can also cut and paste content from a spreadsheet :

animation_2.gif

Obviously, rendering of the table can be tweaked further by changing/adding arguments of the rendering functions in the automatically generated code.

Launch the addin while selecting the name of a variable

In this case, the GUI allows you to select only the desired output format ( it is assumed that the variable you select corresponds to a data frame or similar object containing the data you wish to show as table). After clicking Done the Addin will add in the Rmd document the code needed to render the selected variable as a table with the selected output format. The code will be added at the first empty line below that containing the name of the selected variable.

animation_3.gif

IMPORTANT NOTE: inserttable will make no effort to guarantee that the variable you select is a data.frame. It is up to you to select a meaningful variable!

Usage from the console

You can also use (part of) inserttable functionality from the console by calling function insert_table().

> insert_table(tbl_name = "table_1", nrows = 4, ncols = 4, tbl_format = "DT")

The function will return to the console the code needed to create a empty table of the specified dimensions and render it with the selected format:

animation_4.gif

Download Details:

Author: lbusett
Source Code: https://github.com/lbusett/insert_table 
License: GPL-3.0 license

#r #table #function 

R Function & Addin to Easily insert Tables In Rmd Code Chunks
Nat  Grady

Nat Grady

1660936680

Prefix Function with Their Namespace & Other Development tools

prefixer:: 

Prefix function with their namespace and other tools for writing functions / packages   

Overview

It can be useful to prefix function in a script to prevent use of the wrong one, e.g. stats::filter vs dplyr::filter or plyr::summarise vs dplyr::summarise. This package provide a Shiny gadget to interactively add prefix to function in a script, if a function exist in several packages, you can choose the one you want use.

If you're in a package, you can generate @importFrom tag from function definition and after remove prefix if needed.

Installation :

# with remotes
remotes::install_github("dreamRs/prefixer")

⚠️ functions of this package will modify your scripts

prefixer:: gadget

You can launch the addin via RStudio's Addins menu. Interface looks like this :

fread_dir <- function(path, pattern = "\\.csv$") {
  paths <- list.files(path = path, pattern = pattern, full.names = TRUE)
  files <- lapply(paths, fread)
  files <- setNames(files, paths)
  rbindlist(l = files, idcol = "path")
}

Becomes =>

fread_dir <- function(path, pattern = "\\.csv$") {
  paths <- list.files(path = path, pattern = pattern, full.names = TRUE)
  files <- lapply(paths, data.table::fread)
  files <- stats::setNames(files, paths)
  data.table::rbindlist(l = files, idcol = "path")
}

@importFrom

From prefixed functions, you can generate roxygen @importFrom tag via addin @importFrom.

Or manually with import_from(fun = fread_dir):

#' @importFrom data.table fread rbindlist
#' @importFrom stats setNames
fread_dir <- function(path, pattern = "\\.csv$") {
  paths <- list.files(path = path, pattern = pattern, full.names = TRUE)
  files <- lapply(paths, data.table::fread)
  files <- stats::setNames(files, paths)
  data.table::rbindlist(l = files, idcol = "path")
}

Unprefix

After generated @importFrom tags, you can if you want remove prefix before your functions via addin Unprefix :

#' @importFrom data.table fread rbindlist
#' @importFrom stats setNames
fread_dir <- function(path, pattern = "\\.csv$") {
  paths <- list.files(path = path, pattern = pattern, full.names = TRUE)
  files <- lapply(paths, fread)
  files <- setNames(files, paths)
  rbindlist(l = files, idcol = "path")
}

Roxygen comments

Addin Roxygen comment allow to comment selected line with #'.

Not-ASCII

Addin Not-ASCII escape all not-ASCII characters between quotes to Unicode, to avoid warning in R CMD check :

frenchFileInput <- function(inputId) {
  fileInput(
    inputId = inputId,
    label = "Sélectionner un fichier :",
    buttonLabel = "Parcourir...",
    placeholder = "Aucun fichier sélectionné"
  )
}

becomes =>

frenchFileInput <- function(inputId) {
  fileInput(
    inputId = inputId,
    label = "S\u00e9lectionner un fichier :",
    buttonLabel = "Parcourir...",
    placeholder = "Aucun fichier s\u00e9lectionn\u00e9"
  )
}

Show Non-ASCII files

Show files containing Non-ASCII characters in RStudio markers tabs. This function is similar to tools::showNonASCIIfile.

show_nonascii_file()

Check Rd files

Check if your Rd files (documentation) contains examples and return value:

check_Rd_examples()
# 1 Rd file(s) with no examples. 
#  - unprefix.Rd 

check_Rd_value()
# 2 Rd file(s) with no value. 
#  - prefixer.Rd 
#  - unprefix.Rd 

Count calls

Get functions used in scripts and where they come from, for example functions used in this package:

count_calls("R/")
#                      call  n                  package
# 1                    tags 36                htmltools
# 2              rstudioapi 15                     <NA>
# 3         str_replace_all 15                  stringr
# 4                     div  9                htmltools
# 5                       b  8                     <NA>
# 6            observeEvent  8                    shiny
# 7                     pre  6                htmltools
# 8           set_selection  6                 prefixer
# 9  getSourceEditorContext  5               rstudioapi
# 10             insertText  5               rstudioapi
# ...

Download Details:

Author: DreamRs
Source Code: https://github.com/dreamRs/prefixer 
License: GPL-3.0 license

#r #function #development #tools 

Prefix Function with Their Namespace & Other Development tools
Nat  Grady

Nat Grady

1660821600

Tidyshiny: Interactively Generate Function Calls for The Tidyr Package

tidyshiny

Interactively manipulate data with the tidyr package using this handy shiny gadget.    

Installation

library(devtools)
install_github("MangoTheCat/tidyshiny")

Usage

After launching the gadget with the tidyData function you will be able to set the key and value arguments and select columns. The gadget will preview the data that will be generated from the function call that is returned unless no columns are selected.

library(tidyshiny)

# Create a dataset object for the gadget to detect
testData <- airquality
tidyData()

# Alternatively pass the data to the tidyData function call
tidyData(iris)

This package has been setup to work with RStudio addin's and it will be available from the addins menu after installing the package.

Download Details:

Author: MangoTheCat
Source Code: https://github.com/MangoTheCat/tidyshiny/ 
License: View license

#r #generate #function 

Tidyshiny: Interactively Generate Function Calls for The Tidyr Package
Dexter  Goodwin

Dexter Goodwin

1660382940

Make A Synchronous Function Asynchronous By Running It in A Worker

make-asynchronous

Make a synchronous function asynchronous by running it in a worker

This makes it super simple to offload some expensive work without having to deal with the complex Web Workers API.

Install

npm install make-asynchronous

Usage

import makeAsynchronous from 'make-asynchronous';

const fn = makeAsynchronous(number => {
	return performExpensiveOperation(number);
});

console.log(await fn(2));
//=> 345342

API

makeAsynchronous(function)

Returns a wrapped version of the given function which executes asynchronously in a background thread (meaning it will not block the main thread).

The given function is serialized, so you cannot use any variables or imports from outside the function scope. You can instead pass in arguments to the function.

makeAsynchronousIterable(function)

Make the iterable returned by a function asynchronous by running it in a worker.

import {makeAsynchronousIterable} from 'make-asynchronous';

const fn = makeAsynchronousIterable(function * () {
	yield * performExpensiveOperation(number);
});

for await (const number of fn(2)) {
	console.log(number);
}

fn.withSignal(signal)

The function returned by makeAsynchronous and makeAsynchronousIterable has an additional method which allows an AbortSignal to be provided.

import makeAsynchronous from 'make-asynchronous';

const fn = makeAsynchronous(number => {
	return performExpensiveOperation(number);
});

const controller = new AbortController();
const timeoutId = setTimeout(() => {
	controller.abort();
}, 1000); // 1 second timeout

const result = await fn.withSignal(controller.signal)(2);
clearTimeout(timeoutId);

console.log(result);
//=> 345342

Please upvote this Node.js issue 🙏 It would let us reduce the amount of dependencies and simplify the code.

Works in Node.js and browsers.

Related

Download Details:

Author: Sindresorhus
Source Code: https://github.com/sindresorhus/make-asynchronous 
License: MIT license

#javascript #function #worker 

Make A Synchronous Function Asynchronous By Running It in A Worker

Bun-livereload: Automatically Reload any Imports

bun-livereload

Wrap a function with bun-livereload to automatically reload any imports inside the function the next time it is called.

import liveReload from "bun-livereload";

export default {
  fetch: liveReload(async function (req: Request) {
    const { render } = await import("./my-page.js");
    return new Response(render(req));
  }),
};

Install

bun add bun-livereload

Download Details: 

Author: jarred-sumner
Source Code: https://github.com/jarred-sumner/bun-livereload 

#typescript #load #function 

Bun-livereload: Automatically Reload any Imports
Jamel  O'Reilly

Jamel O'Reilly

1659839100

BartyCrouch: Updates Your Strings Files From Your Code

BartyCrouch

BartyCrouch incrementally updates your Strings files from your Code and from Interface Builder files. "Incrementally" means that BartyCrouch will by default keep both your already translated values and even your altered comments. Additionally you can also use BartyCrouch for machine translating from one language to 60+ other languages. Using BartyCrouch is as easy as running a few simple commands from the command line what can even be automated using a build script within your project.

Requirements

  • Xcode 13.3+ & Swift 5.6+
  • Xcode Command Line Tools (see here for installation instructions)

Getting Started

Installation

Via Homebrew

To install Bartycrouch the first time, simply run the command:

brew install bartycrouch

To update to the newest version of BartyCrouch when you have an old version already installed run:

brew upgrade bartycrouch

Via Mint

To install or update to the latest version of BartyCrouch simply run this command:

mint install FlineDev/BartyCrouch

Configuration

To configure BartyCrouch for your project, first create a configuration file within your projects root directory. BartyCrouch can do this for you:

bartycrouch init

Now you should have a file named .bartycrouch.toml with the following contents:

[update]
tasks = ["interfaces", "code", "transform", "normalize"]

[update.interfaces]
paths = ["."]
subpathsToIgnore = [".git", "carthage", "pods", "build", ".build", "docs"]
defaultToBase = false
ignoreEmptyStrings = false
unstripped = false
ignoreKeys = ["#bartycrouch-ignore!", "#bc-ignore!", "#i!"]

[update.code]
codePaths = ["."]
subpathsToIgnore = [".git", "carthage", "pods", "build", ".build", "docs"]
localizablePaths = ["."]
defaultToKeys = false
additive = true
unstripped = false
ignoreKeys = ["#bartycrouch-ignore!", "#bc-ignore!", "#i!"]

[update.transform]
codePaths = ["."]
subpathsToIgnore = [".git", "carthage", "pods", "build", ".build", "docs"]
localizablePaths = ["."]
transformer = "foundation"
supportedLanguageEnumPath = "."
typeName = "BartyCrouch"
translateMethodName = "translate"

[update.normalize]
paths = ["."]
subpathsToIgnore = [".git", "carthage", "pods", "build", ".build", "docs"]
sourceLocale = "en"
harmonizeWithSource = true
sortByKeys = true

[lint]
paths = ["."]
subpathsToIgnore = [".git", "carthage", "pods", "build", ".build", "docs"]
duplicateKeys = true
emptyValues = true

This is the default configuration of BartyCrouch and should work for most projects as is. In order to use BartyCrouch to its extent, it is recommended though to consider making the following changes:

  1. To speed it up significantly, provide more specific paths for any key containing path if possible (especially in the update.transform section, e.g. ["App/Sources"] for codePaths or ["App/Supporting Files"] for supportedLanguageEnumPaths).
  2. Remove the code task if your project is Swift-only and you use the new transform update task.
  3. If you are using SwiftGen with the structured-swift4 template, you will probably want to use the transform task and change its transformer option to swiftgenStructured.
  4. If you decided to use the transform task, create a new file in your project (e.g. under SupportingFiles) named BartyCrouch.swift and copy the following code:
//  This file is required in order for the `transform` task of the translation helper tool BartyCrouch to work.
//  See here for more details: https://github.com/FlineDev/BartyCrouch

import Foundation

enum BartyCrouch {
    enum SupportedLanguage: String {
        // TODO: remove unsupported languages from the following cases list & add any missing languages
        case arabic = "ar"
        case chineseSimplified = "zh-Hans"
        case chineseTraditional = "zh-Hant"
        case english = "en"
        case french = "fr"
        case german = "de"
        case hindi = "hi"
        case italian = "it"
        case japanese = "ja"
        case korean = "ko"
        case malay = "ms"
        case portuguese = "pt-BR"
        case russian = "ru"
        case spanish = "es"
        case turkish = "tr"
    }

    static func translate(key: String, translations: [SupportedLanguage: String], comment: String? = nil) -> String {
        let typeName = String(describing: BartyCrouch.self)
        let methodName = #function

        print(
            "Warning: [BartyCrouch]",
            "Untransformed \(typeName).\(methodName) method call found with key '\(key)' and base translations '\(translations)'.",
            "Please ensure that BartyCrouch is installed and configured correctly."
        )

        // fall back in case something goes wrong with BartyCrouch transformation
        return "BC: TRANSFORMATION FAILED!"
    }
}
  1. If you don't develop in English as the first localized language, you should update the sourceLocale of the normalize task.
  2. If you want to use the machine translation feature of BartyCrouch, add translate to the tasks list at the top and copy the following section into the configuration file with secret replaced by your Microsoft Translator Text API Subscription Key:
[update.translate]
paths = "."
translator = "microsoftTranslator"
secret = "<#Subscription Key#>"
sourceLocale = "en"

Usage

Before using BartyCrouch please make sure you have committed your code. Also, we highly recommend using the build script method described below.


bartycrouch accepts one of the following sub commands:

  • update: Updates your .strings file contents according to your configuration.
  • lint: Checks your .strings file contents for empty values & duplicate keys.

Also the following command line options can be provided:

  • -v, --verbose: Prints more detailed information about the executed command.
  • -x, --xcode-output: Prints warnings & errors in Xcode compatible format.
  • -w, --fail-on-warnings: Returns a failed status code if any warning is encountered.
  • -p, --path: Specifies a different path than current to run BartyCrouch from there.

update subcommand

The update subcommand can be run with one or multiple of the following tasks:

  • interfaces: Updates .strings files of Storyboards & XIBs.
  • code: Updates Localizable.strings file from NSLocalizedString entries in code.
  • transform: A mode where BartyCrouch replaces a specific method call to provide translations in multiple languages in a single line. Only supports Swift files.
  • translate: Updates missing translations in other languages than the source language.
  • normalize: Sorts & cleans up .strings files.

In order to configure which tasks are executed, edit this section in the config file:

[update]
tasks = ["interfaces", "code", "transform", "normalize"]

Options for interfaces

  • paths: The directory / directories to search for Storyboards & XIB files.
  • subpathsToIgnore: The subpaths to be ignored inside the directories found via the paths option.
  • defaultToBase: Add Base translation as value to new keys.
  • ignoreEmptyStrings: Doesn't add views with empty values.
  • unstripped: Keeps whitespaces at beginning & end of Strings files.
  • ignoreKeys: Keys (e.g. in the comment) indicating that specific translation entries should be ignored when generating String files. Useful to ignore strings that are gonna be translated in code.

Options for code

  • codePaths: The directory / directories to search for Swift code files.
  • subpathsToIgnore: The subpaths to be ignored inside the directories found via the paths option.
  • localizablePaths: The enclosing path(s) containing the localized Localizable.strings files.
  • defaultToKeys: Add new keys both as key and value.
  • additive: Prevents cleaning up keys not found in code.
  • customFunction: Use alternative name to NSLocalizedString.
  • customLocalizableName: Use alternative name for Localizable.strings.
  • unstripped: Keeps whitespaces at beginning & end of Strings files.
  • plistArguments: Use a plist file to store all the code files for the ExtractLocStrings tool. (Recommended for large projects.)
  • ignoreKeys: Keys (e.g. in the comment) indicating that specific translation entries should be ignored when generating String files.

Options for transform

  • codePaths: The directory / directories to search for Swift code files.
  • subpathsToIgnore: The subpaths to be ignored inside the directories found via the paths option.
  • localizablePaths: The enclosing path(s) containing the localized Localizable.strings files.
  • transformer: Specifies the replacement code. Use foundation for NSLocalizedString or swiftgenStructured for L10n entries.
  • supportedLanguageEnumPath: The enclosing path containing the SupportedLanguage enum.
  • typeName: The name of the type enclosing the SupportedLanguage enum and translate method.
  • translateMethodName: The name of the translate method to be replaced.
  • customLocalizableName: Use alternative name for Localizable.strings.
  • separateWithEmptyLine: Set to false if you don't want to have empty lines between Strings entries. Defaults to `true.

Options for translate

  • paths: The directory / directories to search for Strings files.
  • subpathsToIgnore: The subpaths to be ignored inside the directories found via the paths option.
  • translator: Specifies the translation API. Use microsoftTranslator or deepL.
  • secret: Your Microsoft Translator Text API Subscription Key or Authentication Key for DeepL API.
  • sourceLocale: The source language to translate from.
  • separateWithEmptyLine: Set to false if you don't want to have empty lines between Strings entries. Defaults to `true.

Options for normalize

  • paths: The directory / directories to search for Strings files.
  • subpathsToIgnore: The subpaths to be ignored inside the directories found via the paths option.
  • sourceLocale: The source language to harmonize keys of other languages with.
  • harmonizeWithSource: Synchronizes keys with source language.
  • sortByKeys: Alphabetically sorts translations by their keys.
  • separateWithEmptyLine: Set to false if you don't want to have empty lines between Strings entries. Defaults to `true.

lint subcommand

The lint subcommand was designed to analyze a project for typical translation issues. The current checks include:

  • duplicateKeys: Finds duplicate keys within the same file.
  • emptyValues: Finds empty values for any language.

Note that the lint command can be used both on CI and within Xcode via the build script method:

  • In Xcode the -x or --xcode-output command line argument should be used to get warnings which point you directly to the found issue.
  • When running on the CI you should specify the -w or --fail-on-warnings argument to make sure BartyCrouch fails if any warnings are encountered.

Localization Workflow via transform

When the transform update task is configured (see recommended step 4 in the Configuration section above) and you are using the build script method, you can use the following simplified process for writing localized code during development:

  1. Instead of NSLocalizedString calls you can use BartyCrouch.translate and specify a key, translations (if any) and optionally a comment. For example:
self.title = BartyCrouch.translate(key: "onboarding.first-page.header-title",  translations: [.english: "Welcome!"])
  1. Once you build your app, BartyCrouch will automatically add the new translation key to all your Localizable.strings files and add the provided translations as values for the provided languages.
  2. Additionally, during the same build BartyCrouch will automatically replace the above call to BartyCrouch.translate with the proper translation call, depending on your transformer option setting.

The resulting code depends on your transformer option setting:

When set to foundation, the above code will transform to:

self.title = NSLocalizedString("onboarding.first-page.header-title", comment: "")

When set to swiftgenStructured it will transform to:

self.title = L10n.Onboarding.FirstPage.headerTitle

Advantages of transform over the code task:

  • You can provide translations for keys without switching to the Strings files.
  • In case you use SwiftGen, you don't need to replace calls to NSLocalizedString with L10n calls manually after running BartyCrouch.
  • Can be combined with the machine translation feature to provide a source language translation in code and let BartyCrouch translate it to all supported languages in a single line & without ever leaving the code.

Disadvantages of transform over the code task:

  • Only works for Swift Code. No support for Objective-C. (You can use both methods simultaneously though.)
  • Xcode will mark the freshly transformed code as errors (but build will succeed anyways) until next build.
  • Not as fast as code since SwiftSyntax currently isn't particularly fast. (But this should improve over time!)

NOTE: As of version 4.x of BartyCrouch formatted localized Strings are not supported by this automatic feature.

Build Script

In order to truly profit from BartyCrouch's ability to update & lint your .strings files you can make it a natural part of your development workflow within Xcode. In order to do this select your target, choose the Build Phases tab and click the + button on the top left corner of that pane. Select New Run Script Phase and copy the following into the text box below the Shell: /bin/sh of your new run script phase:

export PATH="$PATH:/opt/homebrew/bin"

if which bartycrouch > /dev/null; then
    bartycrouch update -x
    bartycrouch lint -x
else
    echo "warning: BartyCrouch not installed, download it from https://github.com/FlineDev/BartyCrouch"
fi

Next, make sure the BartyCrouch script runs before the steps Compiling Sources (and SwiftGen if used) by moving it per drag & drop, for example right after Target Dependencies.

Now BartyCrouch will be run on each build and you won't need to call it manually ever (again). Additionally, all your co-workers who don't have BartyCrouch installed will see a warning with a hint on how to install it.

Note: Please make sure you commit your code using source control regularly when using the build script method.


Exclude specific Views / NSLocalizedStrings from Localization

Sometimes you may want to ignore some specific views containing localizable texts e.g. because their values are going to be set programmatically.

For these cases you can simply include #bartycrouch-ignore! or the shorthand #bc-ignore! into your value within your base localized Storyboard/XIB file. Alternatively you can add #bc-ignore! into the field "Comment For Localizer" box in the utilities pane.

This will tell BartyCrouch to ignore this specific view when updating your .strings files.

Here's an example of how a base localized view in a XIB file with partly ignored strings might look like:

Here's an example with the alternative comment variant:

You can also use #bc-ignore! in your NSLocalizedString macros comment part to ignore them so they are not added to your Localizable.strings. This might be helpful when you are using a .stringsdict file to handle pluralization (see docs).

For example you can do something like this:

func updateTimeLabel(minutes: Int) {
  String.localizedStringWithFormat(NSLocalizedString("%d minute(s) ago", comment: "pluralized and localized minutes #bc-ignore!"), minutes)
}

The %d minute(s) ago key will be taken from Localizable.stringsdict file, not from Localizable.strings, that's why it should be ignored by BartyCrouch.

Donation

BartyCrouch was brought to you by Cihat Gündüz in his free time. If you want to thank me and support the development of this project, please make a small donation on PayPal. In case you also like my other open source contributions and articles, please consider motivating me by becoming a sponsor on GitHub or a patron on Patreon.

Thank you very much for any donation, it really helps out a lot! 💯

Migration Guides

See the file MIGRATION_GUIDES.md.

Contributing

Contributions are welcome. Feel free to open an issue on GitHub with your ideas or implement an idea yourself and post a pull request. If you want to contribute code, please try to follow the same syntax and semantic in your commit messages (see rationale here). Also, please make sure to add an entry to the CHANGELOG.md file which explains your change.

After Release Checklist:

  1. Run make portable_zip to generate .build/release/portable_bartycrouch.zip
  2. Create new release with text from new CHANGELOG.md section & attach portable_bartycrouch.zip as binary
  3. Run pod trunk push to make a new release known to CocoaPods
  4. Update tag and revision in Formula/bartycrouch.rb, commit & push change
  5. Run brew bump-formula-pr bartycrouch --tag=<tag> --revision=<revision>

Author: FlineDev
Source Code: https://github.com/FlineDev/BartyCrouch
License: MIT license

#ios #swift 

BartyCrouch: Updates Your Strings Files From Your Code
Royce  Reinger

Royce Reinger

1659338160

Soundex: A Soundex Function Coded in Ruby

Ruby function to find american Soundex of an word

Based upon https://en.wikipedia.org/wiki/Soundex

Usage

Install by using this code

$ gem install soundex

Use it like this

require 'soundex'

Soundex.new "Madras"
Soundex.new "Madharas"

Download Details: 

Author: Mindaslab
Source Code: https://github.com/mindaslab/soundex 

#ruby #function 

Soundex: A Soundex Function Coded in Ruby

Comment créer un projet de liste de tâches en Python avec Tkinter

Nous allons implémenter une simple liste de tâches en python dans laquelle nous pouvons ajouter une tâche et la supprimer une fois terminée. Nous utiliserons un package Python appelé Tkinter qui est une bibliothèque d'interface graphique Python largement utilisée. Il est livré avec python, nous n'avons donc pas besoin de le télécharger ou de l'installer séparément, nous pouvons simplement l'importer et commencer avec.

Une interface graphique est essentiellement un moyen d'interagir et de présenter des informations aux utilisateurs. L'un des principaux avantages de l'utilisation de Tkinter est qu'il fonctionne bien sur n'importe quelle machine, que ce soit Windows, Linux ou macOS.

Dans ce didacticiel, nous allons apprendre à créer un projet de liste de tâches en Python avec Tkinter et d'autres concepts de base de python. Les utilisateurs peuvent ajouter, supprimer, marquer leurs tâches comme terminées.

Étapes pour développer un projet de liste de tâches

1. Importez la bibliothèque Tkinter

#importing packages 
from  tkinter import * 
import tkinter.messagebox

 

2. Créer une fenêtre d'application de liste de tâches

window=Tk()
#giving a title
window.title("DataFlair Python To-Do List APP")
window.mainloop()

3. Créer la mise en page de l'application

 

#creating the initial window
window=Tk()
#giving a title
window.title("DataFlair Python To-Do List APP")


#Frame widget to hold the listbox and the scrollbar
frame_task=Frame(window)
frame_task.pack()

#to hold items in a listbox
listbox_task=Listbox(frame_task,bg="black",fg="white",height=15,width=50,font = "Helvetica")  
listbox_task.pack(side=tkinter.LEFT)

#Scrolldown in case the total list exceeds the size of the given window 
scrollbar_task=Scrollbar(frame_task)
scrollbar_task.pack(side=tkinter.RIGHT,fill=tkinter.Y)
listbox_task.config(yscrollcommand=scrollbar_task.set)
scrollbar_task.config(command=listbox_task.yview)


#Button widget 
entry_button=Button(window,text="Add task",width=50,command=entertask)
entry_button.pack(pady=3)

delete_button=Button(window,text="Delete selected task",width=50,command=deletetask)
delete_button.pack(pady=3)

mark_button=Button(window,text="Mark as completed ",width=50,command=markcompleted)
mark_button.pack(pady=3)


window.mainloop()

 

4. Définir les fonctions de la liste de tâches

 

def entertask():
    #A new window to pop up to take input
    input_text=""
    def add():
        input_text=entry_task.get(1.0, "end-1c")
        if input_text=="":
            tkinter.messagebox.showwarning(title="Warning!",message="Please Enter some Text")
        else:
            listbox_task.insert(END,input_text)
            #close the root1 window
            root1.destroy()
    root1=Tk()
    root1.title("Add task")
    entry_task=Text(root1,width=40,height=4)
    entry_task.pack()
    button_temp=Button(root1,text="Add task",command=add)
    button_temp.pack()
    root1.mainloop()
    

#function to facilitate the delete task from the Listbox
def deletetask():
    #selects the selected item and then deletes it 
    selected=listbox_task.curselection()
    listbox_task.delete(selected[0])
#Executes this to mark completed 

def markcompleted():
    marked=listbox_task.curselection()
    temp=marked[0]
    #store the text of selected item in a string
    temp_marked=listbox_task.get(marked)
    #update it 
    temp_marked=temp_marked+" ✔"
    #delete it then insert it 
    listbox_task.delete(temp)
    listbox_task.insert(temp,temp_marked)

Veuillez télécharger le code source de la liste de tâches python : To Do List Python Project Code

Vous pouvez maintenant faire votre premier pas avec succès pour devenir un développeur python et terminer votre projet de liste de tâches python.