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.
protocol GreetingServiceProtocol {
func greet(name: String) -> String
} Implementation
Conform to the protocol with the actual logic.
final class GreetingService: GreetingServiceProtocol {
func greet(name: String) -> String {
"Hello, \(name)!"
}
} Registration
Create an AppDependencies struct conforming to ForgeRegisterProtocol to hold all registrations.
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:
import SwiftUI
import ForgeInject
@main
struct TaskFlowApp: App {
init() {
let container = ForgeContainer()
AppDependencies().registerDependencies(in: container)
ForgeContainer.shared = container
}
var body: some Scene {
WindowGroup {
GreetingView()
}
}
} import UIKit
import ForgeInject
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
let container = ForgeContainer()
AppDependencies().registerDependencies(in: container)
ForgeContainer.shared = container
window = UIWindow()
window?.rootViewController = GreetingViewController()
window?.makeKeyAndVisible()
return true
}
} ViewModel
@Injectable generates an init that defaults to resolving greetingService from ForgeContainer.shared. Tests can pass a mock instead — no container required.
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.
struct GreetingView: View {
@State private var viewModel = GreetingViewModel()
var body: some View {
VStack(spacing: 16) {
Text(viewModel.message)
.font(.title)
Button("Say Hello") {
viewModel.sayHello()
}
}
.padding()
}
} import UIKit
import ForgeInject
final class GreetingViewController: UIViewController {
private let viewModel = GreetingViewModel()
private let label = UILabel()
private let button = UIButton(type: .system)
override func viewDidLoad() {
super.viewDidLoad()
label.font = .preferredFont(forTextStyle: .title1)
label.textAlignment = .center
button.setTitle("Say Hello", for: .normal)
button.addAction(UIAction { [weak self] _ in
self?.viewModel.sayHello()
self?.label.text = self?.viewModel.message
}, for: .touchUpInside)
let stack = UIStackView(arrangedSubviews: [label, button])
stack.axis = .vertical
stack.spacing = 16
stack.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(stack)
NSLayoutConstraint.activate([
stack.centerXAnchor.constraint(equalTo: view.centerXAnchor),
stack.centerYAnchor.constraint(equalTo: view.centerYAnchor),
])
}
}