FI
ForgeInject

Basic App

A minimal end-to-end example — protocol, implementation, registration, and resolution.

Protocol

Define the contract your code depends on. Consumers never reference the concrete type directly.

GreetingServiceProtocol.swift
protocol GreetingServiceProtocol {
    func greet(name: String) -> String
}

Implementation

Conform to the protocol with the actual logic.

GreetingService.swift
final class GreetingService: GreetingServiceProtocol {
    func greet(name: String) -> String {
        "Hello, \(name)!"
    }
}

Registration

Create an AppDependencies struct conforming to ForgeRegisterProtocol to hold all registrations.

AppDependencies.swift
import ForgeInject

struct AppDependencies: ForgeRegisterProtocol {
    func registerDependencies(in container: ForgeContainerProtocol) {
        container.register(with: .singleton) { _ in
            GreetingService() as GreetingServiceProtocol
        }
    }
}

Then call it from your app entry point:

ViewModel

@Injectable generates an init that defaults to resolving greetingService from ForgeContainer.shared. Tests can pass a mock instead — no container required.

GreetingViewModel.swift
import ForgeInject

@Injectable
@Observable
final class GreetingViewModel {
    let greetingService: GreetingServiceProtocol

    var message = ""

    func sayHello() {
        message = greetingService.greet(name: "World")
    }
}

View

A standard view that uses the view model. The view has no awareness of the dependency injection layer.