Skip to content
Jasper Blues edited this page Apr 4, 2021 · 9 revisions

After completing the quick start, you may using the main track (see side-bar) starting with Types of Injections, as a reference.

Quick Start

Here's how to get up and running with Pilgrim in two minutes. There are three steps.

Bootstrap

(Optionally) bootstrap the default assembly type when the app launches, for example in main.swift:

class MyApplication: UIApplication {

    override init() {
        AssemblyHolder.defaultAssemblyType = QuestAssembly.self
    }
    
}
UIApplicationMain(CommandLine.argc, CommandLine.unsafeArgv, "MyApplication", "MyAppDelegate")

This step allows using the Assembled property wrapper (step 3) without explicitly specifying an assembly type.

Define Assemblies

An assembly (also known as the composition root) is where we declare the key actors within an application architecture, their lifecycles and how they interact in order to fulfil their roles.

class QuestAssembly: PilgrimAssembly {

  let childAssembly = AssemblyHolder.shared(ChildAssembly.self)

  override func makeBindings() {
    super.makeBindings()
    makeInjectable(knight, byType: Knight.self)
    makeInjectable(holyGrailQuest, byType: Quest.self)
    makeInjectable(holyGrailQuest, byKey: "damselQuest")
    importBindings(childAssembly)
  }

  func knight() -> Knight {
    weakShared{ Knight(quest: damselInDistressQuest()) }
  }

  /**
   HolyGrailQuest is a struct that conforms to the Quest protocol.
   */
  func holyGrailQuest() -> Quest {
    shared{ HolyGrailQuest() }
  }

  /**
   Damsel's name is Bruce and the Knight is a lovely lass named Fiona. 
   */
  func damselInDistressQuest() -> Quest {
    shared { DamselInDistressQuest() }
  }
}

In the example above we can see:

  • Functions that define architectural components. For example a Knight can fulfil a role when provided with a Quest. Each of these components has a lifecycle.
  • makeBindings : We can obtain top-level build instances from the DI container using a property wrapper. This is described in the next step.

Inject Assembled Instances

Now we can inject built instances into top-level classes using the Assembled property wrapper, as follows:

class StoryViewController : UIViewController {

    /**
     The built instance is auto-injected from the QuestAssembly 
    */
    @Assembled var knight: Knight; 

    private(set) var story: Story 
  
    init(story: Story) {
      self.story = story
    }
}

The built instance is auto-injected from the QuestAssembly. That's it!

Notes

  • In makeBindings we're providing the information on how to resolve - either by type, which is the default, or, say if you have more than one components conforming to the same protocol, you can use String keys. Note that you're binding the function that will emit the built instance, not the return value (so don't add brackets!).
  • Use the assembly to define how components interact. For example a Quest is injected into a Knight - this happens within the assembly.
  • Use the Assembled property decorator to obtain built instances for injection into top-level components - eg a view controller, in a UIKit app.
  • Assemblies can be layered - I'll explain this concept in the User Guide.

Sample App

Sometimes the easiest way is to see it in action. There's a sample app here.

Weather Report

Quick Start!

Get started in two minutes.

Main Track

Get familiar with Pilgrim.

Advanced Topics

Become a Pilgrim expert.

Under the Hood

For contributors or curious folks.

Clone this wiki locally