RouteComposer

repository·master·Indexed 21 days ago

https://github.com/ekazaev/route-composer

A protocol-oriented library for iOS that provides Cocoa UI abstractions to handle view controller composition, navigation, and deep linking, serving as a universal replacement for the Coordinator pattern.

Tokens
15.7K
Snippets
52
Records
67
Agent score
76%

What's inside RouteComposer

  1. What is SwiftFormat?

    master
    SwiftFormat is a code library and command-line tool designed to reformat Swift code on macOS, Linux, or Windows. Beyond simple whitespace adjustment, it can perform advanced transformations such as inserting or removing implicit self, removing redundant parentheses, and correcting deviations from standard Swift idioms to enforce a consistent coding style across projects.
  2. Configure SwiftFormat Rules

    master

    Rules are functions that apply changes to code. Most are enabled by default.

    Command Line Management:

    • List rules: --rules (shows enabled/disabled status).
    • Get rule details: --rule-info [rule_name] (or --rule-info for all).
    • Disable rules: --disable rule1,rule2 or multiple --disable flags.
    • Enable rules: --enable rule1,rule2 or multiple --enable flags.
    • Strict mode: To avoid automatic opt-ins to new rules, use --disable all and then manually --enable specific rules, or use --rules rule1,rule2 to only enable a specific set.

    Inline Comment Management: Use swiftformat: directives within Swift files:

    • // swiftformat:disable <rule1> <rule2>
    • // swiftformat:enable <rule1> <rule2>
    • // swiftformat:disable all / // swiftformat:enable all
    • // swiftformat:disable:next <rule1> (disables rule for the next line only; no manual re-enable required).
    • // swiftformat:disable:this <rule1> (disables for current line).
    • // swiftformat:disable:previous <rule1> (disables for previous line).
    --disable redundantSelf,trailingClosures
    --enable isEmpty
    
    // swiftformat:disable <rule1> [<rule2> [rule<3> ...]]
  3. Specify Swift Version and Language Mode

    master

    Some rules require specific Swift versions. If not specified, they may be disabled.

    Swift Compiler Version:

    1. Use the --swift-version command-line argument.
    2. Add --swift-version to your .swiftformat file.
    3. Add a .swift-version file to your project directory (this takes precedence over the --swift-version argument).

    Swift Language Mode: This is distinct from the compiler version (e.g., using Swift 6.0 compiler with Swift 5 language mode). Use --language-mode in CLI or .swiftformat files. If not specified, it defaults to the default mode of the specified compiler version (usually Swift 5.x).

    --swift-version 5.9
    --language-mode 6
  4. Core concepts of RouteComposer: Factory, Finder, and Action

    master

    RouteComposer is built around three main entities that the host application must define to support navigation:

    1. Factory: Responsible for building view controllers.
    2. Finder: Responsible for finding the appropriate destination or state.
    3. Action: Responsible for executing the navigation transition.

    Each of these entities uses two associatedtype parameters:

    • ViewController: The type of view controller being managed (e.g., UINavigationController, CustomViewController).
    • Context: A payload object passed from the router to the view controllers. It is not a View Model or Presenter; it is the minimal information required to identify or configure the view (e.g., a UUID for a productID). It answers: "What do I need to present this view?" and "Am I already presenting this view for this specific context?"
  5. Configure SwiftFormat Options

    master

    Options control the behavior of rules. You can configure them via command-line arguments, a .swiftformat configuration file, or inline comments.

    Command Line: Use --[option_name] [value]. To see all available options, use --options.

    Configuration File: Create a .swiftformat file in your project directory. Each line should contain one option.

    Inline Comments: Use // swiftformat:options to set options for a specific file or range. You can use modifiers to target specific lines:

    • :this: The current line.
    • :next: The next line.
    • :previous: The previous line.
    // Apply to the whole file
    // swiftformat:options --indent 2 --allman true
    
    // Apply only to this line
    let indexUrl: URL // swiftformat:options:this --preserve-acronyms url
    
    // Apply to the next line
    // swiftformat:options:next --semicolons inline
    doTheThing(); print("Did the thing")
    // swiftformat:options --indent 2 --allman true
    
    let indexUrl: URL // swiftformat:options:this --preserve-acronyms url
    
    // swiftformat:options:next --semicolons inline
    doTheThing(); print("Did the thing")
  6. How ContainerAdapters work with Container View Controllers

    master

    RouteComposer manages navigation within ContainerViewControllers (such as UINavigationController, UITabBarController, and UISplitViewController). Because each container has unique methods for interacting with its children, RouteComposer uses ContainerAdapters to abstract these interactions.

    • Built-in Adapters: RouteComposer includes built-in adapters for standard UIKit container view controllers.
    • Custom Adapters: If you use custom container view controllers or those from third-party libraries, you must implement your own ContainerAdapter to allow RouteComposer to switch tabs or manage visibility correctly.

    Refer to the ContainerAdapter protocol documentation for implementation details.

    // Refer to the ContainerAdapter protocol for implementation details
    // https://ekazaev.github.io/route-composer/Protocols/ContainerAdapter.html
  7. How the Router parses configuration

    master

    The Router processes a chain of steps sequentially. For each step, it uses a Finder to check if the target UIViewController exists.

    1. Search Phase: The Router iterates through the chain until a Finder successfully locates the described UIViewController.
    2. Construction Phase: Once found, the Router moves backwards through the chain, using each step's Factory to create the required UIViewController and applying its associated Action to integrate it into the navigation stack.

    Mental Model: Think of configuration as defining a path for a user who could be anywhere in the app (e.g., arriving via a Universal Link) to reach a specific destination.

  8. Prevent unexpected rule changes during upgrades

    master

    To ensure that upgrading SwiftFormat doesn't introduce new formatting rules that surprise you, use the --rules argument. By providing an exclusive list of rules in your SwiftFormat configuration, only those specified rules will be executed, and any new rules added in newer versions of SwiftFormat will be ignored.

    # Example usage of specifying an exclusive list of rules
    swiftformat --rules rule1,rule2,rule3 /path/to/code
  9. Helping entities: RoutingInterceptor, ContextTask, and PostRoutingTask

    master

    In addition to the core entities, RouteComposer provides three helping entities that you can implement to handle specific logic during the routing lifecycle:

    • RoutingInterceptor: Used to intercept and potentially modify the routing process.
    • ContextTask: Used to handle tasks related to the Context during routing.
    • PostRoutingTask: Used to execute actions after a routing operation has completed.
  10. Install the SwiftFormat Xcode Source Editor Extension

    master

    The Xcode extension allows you to trigger formatting via the Editor > SwiftFormat menu within Xcode.

    Installation

    Via Homebrew (Recommended):

    brew install --cask swiftformat-for-xcode

    To update: brew upgrade --cask swiftformat-for-xcode.

    Manual Installation:

    1. Download the latest release from the GitHub Releases page.
    2. Unpack the zip archive.
    3. Drag SwiftFormat for Xcode.app into your Applications folder.

    Usage

    1. Launch the application from your Applications folder.
    2. Follow the on-screen instructions.
    3. Restart Xcode.
    4. Access formatting via the Editor menu in Xcode.

    Note: Configuration is managed within the SwiftFormat for Xcode host application. You can import/export configurations via the File menu, but you must manually re-import .swiftformat files if they change, as the extension does not auto-detect changes to external config files.

  11. Use SwiftFormat as a Swift Package Manager Plugin

    master

    If you are using Swift 5.6 or higher, you can use SwiftFormat as a command plugin. The plugin automatically detects and honors an existing .swiftformat configuration file in your package root.

    Setup

    Add SwiftFormat to your Package.swift dependencies:

    Usage

    From Command Line

    Use the --allow-writing-to-package-directory flag to permit the plugin to modify files. You can use --target to limit formatting to a specific target and pass additional arguments like --swift-version.

    From Xcode

    In Xcode 14+, you can trigger the command plugin directly from the Xcode interface for a Swift package or an Xcode project.

    // Package.swift
    dependencies: [
        .package(url: "https://github.com/nicklockwood/SwiftFormat", from: "0.58.7"),
    ]
    # CLI Usage
    swift package plugin --allow-writing-to-package-directory swiftformat --target MyLibrary --swift-version 5.6 --verbose
  12. Configure SwiftFormat as a Git pre-commit hook

    master

    To ensure code is formatted before every commit, you can use a Git pre-commit hook combined with git-format-staged.

    Setup Steps

    1. Install the SwiftFormat command-line tool locally.
    2. Install git-format-staged.
    3. Create or edit .git/hooks/pre-commit in your project root.
    4. Add the script provided below.
    5. Make the hook executable by running chmod +x .git/hooks/pre-commit.

    Important Considerations

    • Version Consistency: This method uses your local installation of SwiftFormat. In collaborative projects, different team members might use different versions, leading to inconsistent formatting in commits. For teams, consider using a post-commit hook on your CI server instead.
    • GUI Clients: If using a Git GUI like Tower, you may need additional configuration to ensure hooks run correctly.
    #!/bin/bash
    git-format-staged --formatter "swiftformat stdin --stdin-path '{}'" "*.swift"