Resolver, the 700 line Swift dependency injection framework its author retired
Swift Dependency Injection / Service Locator framework (Deprecated)
At a glance
- What is it?
- A single file service locator for iOS that shipped property wrappers, nested containers and five lifetime scopes, and that the same author has since deprecated in favour of Factory.
- Who is it for?
- Resolver still does one thing well: giving an iOS codebase injection with almost no ceremony, which is why codebases built against it keep working without modification. A new project has no reason to start here, because the author states plainly in the README that Resolver is officially deprecated and replaced by Factory, and that Factory is compile-time safe and smaller.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 99 days ago.
- What is it written in?
- Mainly Swift, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 7, 2026, and from our analysis. They are not legal advice.
Editorial analysis
One Swift file carrying the whole container
Resolver is described in its own repository metadata as a Swift dependency injection and service locator framework, and the description ends with the word Deprecated. That is not a warning bolted on by the platform. The first line of the README after the logo announces that Resolver is officially deprecated and replaced by the author's Factory, calls Factory a true container based system that is compile-time safe, and states that Factory is smaller, lighter and faster. The author then says that as good as Resolver was, Factory is better.
That framing matters for anyone evaluating the code today, because the project is still usable and still MIT licensed, but its author has pointed it at a successor. Resolver is 2,214 stars and 196 forks on a master branch, not archived, with the last push on 2026-06-30. So the code is not frozen in a broken state, it is maintained as a legacy library while attention moves elsewhere.
What the project actually is, mechanically, is very small. The README says it is implemented in just over 700 lines of actual code in a single file, and the repository tree backs that up with a Resolver.podspec, a Package.swift, a Tests directory and a Resolver.xcodeproj directory. The dependency injection documentation is split into separate files under Documentation, with pages for Injection, Scopes, Protocols, Types, Optionals, Names, Arguments, Containers, CyclicDependencies, Storyboards and Threads. So the implementation is tiny and the explanation of it is a book.
Six strategies behind one registration call
The README lists six classic dependency injection strategies and says Resolver supports all of them: interface injection, property injection, constructor injection, method injection, service locator, and annotation injection, which it marks as new. Each links to a page under Documentation that carries a short description, an example, and the trade-offs.
The interesting part is what having all six means in practice. Service locator is the pattern most people associate with this library, because you ask the shared Resolver object for a type at the moment you need it, and any type in the program can be reached that way. That convenience is also the thing that tends to make locator patterns unpopular with people who want dependencies visible at the point of use. Resolver's position is that you can start from the locator and then move specific types toward injection as the code gets clearer, which is why property wrappers exist at all.
Argument passing is part of the same design rather than an afterthought. The README notes that Resolver 1.2 added built-in support for multiple arguments, and the update notes say that 1.2 changed how arguments are passed to the registration factory, which was a breaking change. That is the shape of this library: a small runtime that gets refined as needs appear, at the cost of occasional migration work.
Property wrappers that resolve at the point of declaration
This is the feature that gave Resolver its reach, and it is only a handful of lines. Resolver supports resolving services using the Swift 5.1 property wrapper syntax, and the README shows it on a view controller:
class BasicInjectedViewController: UIViewController {
@Injected var service: XYZService
@LazyInjected var service2: XYZLazyService
@WeakLazyInjected var service3: XYZAnotherLazyService?
}Add the keyword to a property declaration and the dependency is resolved. There is no init parameter to thread through and no factory closure at the call site, which is the friction that makes constructor injection verbose in a view controller hierarchy. The three wrappers differ in timing: `@Injected` resolves immediately, `@LazyInjected` defers until first use, and `@WeakLazyInjected` holds its service weakly, which matters for objects that would otherwise create a retain cycle through the view controller. The optional type on the third one is not decorative, since a weak reference cannot promise a value.
There is a fourth wrapper for the SwiftUI generation. The README mentions `@InjectedObject`, which injects observable objects into SwiftUI views, so the library covers both UIKit and SwiftUI call sites rather than only the framework it shipped with.
Five scopes, named instances and nested containers
Lifetime control is where a service locator turns into something you have to think about. Resolver documents five scopes: Application, Cached, Graph, Shared and Unique, and the README tells readers that if they read nothing else, they should read the Automatic Type Inference page, the Scopes page and the Optionals page. Automatic type inference is what lets a property declaration name a protocol without a registration name, and the README claims that it also means writing roughly 40 to 60 percent less injection code.
Namespaces arrived in 1.3, and the README frames them as a possible breaking change. Registering named instances gives better autocompletion and, by the author's account, reduces runtime lookup errors, since a mistyped name now fails at a place the compiler can see. The 1.4.5 release added Hashable and Equatable conformance to `Resolver.Name`, which is the small piece that makes names usable as dictionary and set keys.
Containers are the newer idea. Resolver 1.5, published in October 2021, added a `.container` scope that lives for the lifetime of a given Resolver container, added `init(child:)` to replace the deprecated `init(parent:)`, and removed deprecated scopes from the Resolver base class. That release also reworked `ResolverRegistration` so external services are not reaching into its internals, based on two community pull requests. The direction is clear: moving away from a single global registry toward explicit, nestable containers. Version 1.4 also made direct access to Resolver's scopes deprecated, which is why the release notes are worth reading before changing registration code.
Installing through CocoaPods, SwiftPM or one copied file
Resolver supports CocoaPods and the Swift Package Manager, and the pod line is short enough to state outright:
pod "Resolver"There is a third option that suits small projects. Resolver is just a single source file called Resolver.swift, so the README says it is easy to download the file and add it to the project directly. For a framework this small that is a reasonable choice, since it avoids adding a dependency resolver to a build that has no other need for one.
The version constraints are stated plainly: Resolver 1.4 supports Swift 5.3, and the minimum iOS version for that release is iOS 11. The installation guide covers earlier versions. The repository also carries Package.resolved and a .swiftpm directory, so SwiftPM is a first-class path rather than a retrofit, and the presence of Tests and a podspec means both package managers are exercised against the same source.
Two claims in the README are worth separating from the mechanics. Resolver is written in 100 percent Swift 5 with no Objective-C code, no method swizzling and no internal dependency on the Objective-C runtime, which matters on iOS because runtime swizzling is a common source of App Store review friction. The README also states that Resolver is thread safe assuming your own objects are thread safe, an improvement made in version 1.4.
The performance number, the comparison and the parts that are quiet
The comparison the README offers is with Swinject and its Storyboard integration. The claim is that Resolver is about 800 percent faster than Swinject at resolving dependency chains. That is a project-reported figure from its own README, measured by its author, and the README does not publish the benchmark harness, the input shape or the machine. Treat it as a directional claim rather than a number to plan around.
The architectural argument behind it is checkable, though. A framework with no Objective-C runtime dependency and roughly 700 lines of code has less to do per resolution than a container built on runtime introspection, so the direction of the difference is plausible even if the exact multiple is not something the repository substantiates. Swinject itself is described in the README as a great dependency injection system, which is a fair nod from a competing implementation.
What the repository does not offer is much beyond the README. The material for this project carries no example files and no file contents, so there is no sample application to read at the source level, though the README points at a separate public Builder repository described as a master/detail style iOS app demonstrating MVVM construction with Resolver, mocked user data for development, and the same mocks in unit tests. Storyboard support and cyclic dependency support are both listed as features with documentation pages, and the Changelog and CHANGELOG entry at the root suggest the update history lives there rather than in release notes.
Editorial conclusion
Resolver still does one thing well: giving an iOS codebase injection with almost no ceremony, which is why codebases built against it keep working without modification. A new project has no reason to start here, because the author states plainly in the README that Resolver is officially deprecated and replaced by Factory, and that Factory is compile-time safe and smaller. Start with Factory if you are choosing today, and read Resolver's Scopes and Types documentation if you are maintaining something already built on the single-file service locator. The 1.5.0 release notes are the file to check before touching any registration code, because that release deprecated direct scope access.
Frequently asked questions
Why was Resolver deprecated and what replaced it?
The author deprecated Resolver in favour of Factory, a separate dependency injection system from the same repository. The README states that Factory is a true container based system, is compile-time safe, and is smaller, lighter and faster than Resolver, and that the author considers it better. Resolver is not archived, so existing code keeps working.
What is the difference between @Injected, @LazyInjected and @WeakLazyInjected?
All three are property wrappers that resolve a dependency without passing it through an initializer. `@Injected` resolves immediately, `@LazyInjected` waits until the property is first used, and `@WeakLazyInjected` holds the resolved object weakly and requires an optional type, which is useful for services that would otherwise be retained by the object that injects them. A fourth wrapper, `@InjectedObject`, covers observable objects in SwiftUI views.
Which scopes does Resolver provide and which should a new registration use?
The documented scopes are Application, Cached, Graph, Shared and Unique, and version 1.5 added a container scope that lives as long as its Resolver container. Version 1.4 deprecated accessing Resolver's scopes directly, so the Scopes documentation is the place to confirm the current API. Resolver is a service locator, so scope selection is a real decision rather than a default.
How is Resolver installed in an iOS project?
CocoaPods and the Swift Package Manager are both supported, with `pod "Resolver"` as the pod declaration. Because the library is a single source file called Resolver.swift, it can also be downloaded and added to the project directly. Version 1.4 requires Swift 5.3 and a minimum of iOS 11.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/hmlongco-resolver)