Dependency Injection with Swinject in iOS app

NOVASOLUTIONS.TECHNOLOGY is engaged in the development, support and maintenance of iOS, Android, PWA mobile applications. We have extensive experience and expertise in publishing mobile applications in popular markets like Google Play, App Store, Amazon, AppGallery and others.
Development and support of all types of mobile applications:
Information and entertainment mobile applications
News apps, games, reference guides, online catalogs, weather apps, fitness and health apps, travel apps, educational apps, social networks and messengers, quizzes, blogs and podcasts, forums, aggregators
E-commerce mobile applications
Online stores, B2B apps, marketplaces, online exchanges, cashback services, exchanges, dropshipping platforms, loyalty programs, food and goods delivery, payment systems.
Business process management mobile applications
CRM systems, ERP systems, project management, sales team tools, financial management, production management, logistics and delivery management, HR management, data monitoring systems
Electronic services mobile applications
Classified ads platforms, online schools, online cinemas, electronic service platforms, cashback platforms, video hosting, thematic portals, online booking and scheduling platforms, online trading platforms

These are just some of the types of mobile applications we work with, and each of them may have its own specific features and functionality, tailored to the specific needs and goals of the client.

Showing 1 of 1 servicesAll 1735 services
Dependency Injection with Swinject in iOS app
Medium
~2-3 business days
FAQ
Our competencies:
Development stages
Latest works
  • image_mobile-applications_feedme_467_0.webp
    Development of a mobile application for FEEDME
    756
  • image_mobile-applications_xoomer_471_0.webp
    Development of a mobile application for XOOMER
    624
  • image_mobile-applications_rhl_428_0.webp
    Development of a mobile application for RHL
    1052
  • image_mobile-applications_zippy_411_0.webp
    Development of a mobile application for ZIPPY
    947
  • image_mobile-applications_affhome_429_0.webp
    Development of a mobile application for Affhome
    862
  • image_mobile-applications_flavors_409_0.webp
    Development of a mobile application for the FLAVORS company
    445

Setting up Dependency Injection with Swinject in iOS

Swinject — one of most mature DI containers for Swift. Widely used before SwiftUI era, continues applying in UIKit projects and mixed codebases where SwiftUI exists alongside UIKit. Pure SwiftUI project — look at Factory or native @Environment. For UIKit architectures with MVVM, VIPER or Clean Architecture, Swinject remains relevant choice.

Basic Container Setup

Assembly point for entire dependency graph — Container. Typical organization: AppAssembly protocol + separate Assembly classes per module:

import Swinject

class NetworkAssembly: Assembly {
  func assemble(container: Container) {
    container.register(URLSession.self) { _ in
      URLSession(configuration: .default)
    }.inObjectScope(.container)  // singleton within container

    container.register(APIClient.self) { r in
      DefaultAPIClient(session: r.resolve(URLSession.self)!)
    }.inObjectScope(.container)
  }
}

class AuthAssembly: Assembly {
  func assemble(container: Container) {
    container.register(AuthRepository.self) { r in
      DefaultAuthRepository(
        apiClient: r.resolve(APIClient.self)!,
        keychain: r.resolve(KeychainService.self)!
      )
    }
    container.register(AuthViewModel.self) { r in
      AuthViewModel(repository: r.resolve(AuthRepository.self)!)
    }
  }
}

Initialize in AppDelegate or SceneDelegate:

let assembler = Assembler([
  NetworkAssembly(),
  KeychainAssembly(),
  AuthAssembly(),
  ProfileAssembly()
])
let container = assembler.resolver

Where It Most Often Breaks

Force unwrap on resolve. r.resolve(SomeService.self)! — standard Swinject pattern, but on missed registration this crashes at runtime. Alternative: use Container.loggingBehavior = .verbose in debug builds — then unregistered dependencies logged before crash. For critical dependencies use safeResolve with check in applicationDidFinishLaunching:

func validateRegistrations(_ container: Container) {
  assert(container.resolve(APIClient.self) != nil, "APIClient not registered")
  assert(container.resolve(AuthRepository.self) != nil, "AuthRepository not registered")
}

ObjectScope and memory leaks. .container (singleton) keeps object for entire container lifetime. For ViewModel in UIKit this problem: if ViewModel registered in .container and holds strong reference to ViewController — leak. Register ViewModel in .transient (new object per resolve) or .graph (single object per resolve tree).

Circular dependencies. If AuthViewModel depends on Router, and Router depends on AuthViewModel — Swinject recurses infinitely on resolve. Solved via initCompleted callback to break cycle:

container.register(AuthViewModel.self) { _ in AuthViewModel() }
  .initCompleted { r, vm in
    vm.router = r.resolve(Router.self)
  }

UIKit Navigation Integration

Swinject works well with Coordinator pattern. Coordinator gets resolver and resolves dependencies on screen creation:

class AuthCoordinator {
  private let resolver: Resolver
  init(resolver: Resolver) { self.resolver = resolver }

  func showLogin() {
    let vm = resolver.resolve(AuthViewModel.self)!
    let vc = LoginViewController(viewModel: vm)
    navigationController.pushViewController(vc, animated: true)
  }
}

Work Included

  • Container and Assembler setup with modular Assembly split
  • All layers registration: network, repositories, ViewModel, services
  • Proper ObjectScope for each type
  • Coordinator or Router integration
  • Registration validation in debug mode
  • Dependency graph documentation

Timeline

2–3 days for typical project with 30–50 registered types. Cost depends on current architecture and refactoring scope.