Настройка Dependency Injection (Factory) в iOS-приложении (SwiftUI)

Настройка Dependency Injection с Factory в iOS-приложении (SwiftUI) Вы интегрируете новый модуль, и при первом запуске — краш: "Swinject: nil while unwrapping". Знакомая картина? В SwiftUI-проектах без DI-контейнера зависимости создаются где попало, тесты требуют переписывания половины кода, а см

Разработка и поддержка любых видов мобильных приложений:

Информационные и развлекательные мобильные приложения
Новостные приложения, игры, справочники, онлайн-каталоги, погодные, фитнес и здоровье, туристические, образовательные, социальные сети и мессенджеры, квиз, блоги и подкасты, форумы, агрегаторы
Мобильные приложения электронной коммерции
Интернет-магазины, B2B-приложения, маркетплейсы, онлайн-обменники, кэшбэк-сервисы, биржи, дропшиппинг-платформы, программы лояльности, доставка еды и товаров, платежные системы
Мобильные приложения для управления бизнес-процессами
CRM-системы, ERP-системы, управление проектами, инструменты для команды продаж, учет финансов, управление производством, логистика и доставка, управление персоналом, системы мониторинга данных
Мобильные приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, платформы предоставления электронных услуг, платформы кешбека, видеохостинги, тематические порталы, платформы онлайн-бронирования и записи, платформы онлайн-торговли

Это лишь некоторые из типы мобильных приложений, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента.

Услуги, которые мы предлагаем
Показано 1 из 1Все 1734 услуг
Настройка Dependency Injection (Factory) в iOS-приложении (SwiftUI)
Средний
~2-3 дня

Наши компетенции:

Часто задаваемые вопросы

Последние работы

  • image_mobile-applications_feedme_467_0.webp
    Разработка мобильного приложения для компании FEEDME
    895
  • image_mobile-applications_xoomer_471_0.webp
    Разработка мобильного приложения для компании XOOMER
    782
  • image_mobile-applications_rhl_428_0.webp
    Разработка мобильного приложения для компании RHL
    1216
  • image_mobile-applications_zippy_411_0.webp
    Разработка мобильного приложения для компании ZIPPY
    1079
  • image_mobile-applications_affhome_429_0.webp
    Разработка мобильного приложения для компании Affhome
    1002
  • image_mobile-applications_flavors_409_0.webp
    Разработка мобильного приложения для компании FLAVORS
    597

Настройка Dependency Injection с Factory в iOS-приложении (SwiftUI)

Вы интегрируете новый модуль, и при первом запуске — краш: "Swinject: nil while unwrapping". Знакомая картина? В SwiftUI-проектах без DI-контейнера зависимости создаются где попало, тесты требуют переписывания половины кода, а смена библиотеки — каскад правок. Мы помогаем настроить Factory — библиотеку, которая ловит ошибки на этапе компиляции, а не в рантайме. Результат: код становится тестируемым, поддерживаемым и готовым к масштабированию.

Factory от Майкла Лонга — это DI-контейнер, спроектированный специально под Swift и SwiftUI. В отличие от Swinject, он не использует строковые ключи и не падает с runtime-исключениями при незарегистрированной зависимости. Всё разрешается в compile time — ошибка конфигурации подсвечивается сразу в Xcode.

Почему Factory лучше Swinject для SwiftUI?

Swinject заточен под UIKit и Objective-C runtime. В SwiftUI его интеграция с @Environment и @StateObject создаёт путаницу: кто владеет ViewModel? Factory использует @Injected property wrapper и органично вписывается в SwiftUI-подход. На практике миграция с Swinject на Factory в проекте финтех-стартапа с 150+ регистрациями сократила количество runtime-крашей на 30%, а время написания unit-тестов — вдвое. Сравните сами:

Критерий Factory Swinject
Проверка зависимостей Compile-time Runtime
Поддержка SwiftUI Нативная Требует обёрток
Простота тестирования register/reset за 2 строки Нужен test container
Строковые идентификаторы Нет Да (риск опечаток)

Factory выигрывает по безопасности и скорости разработки. По нашим оценкам, переход на Factory окупается за 2-3 спринта за счёт снижения багов и ускорения регрессионного тестирования.

Как настроить Container в Factory?

  1. Добавьте пакет Factory через Swift Package Manager.
  2. Создайте extension на Container и опишите фабрики для всех слоёв приложения.
  3. Во View используйте @StateObject с фабрикой контейнера.
  4. Для сервисов применяйте @Injected или @LazyInjected.

Пример регистрации:

import Factory extension Container { var apiClient: Factory<APIClient> { Factory(self) { DefaultAPIClient() }.singleton } var authRepository: Factory<AuthRepository> { Factory(self) { DefaultAuthRepository(apiClient: self.apiClient()) } } var authViewModel: Factory<AuthViewModel> { Factory(self) { AuthViewModel(repository: self.authRepository()) } } } 

Использование во View:

struct LoginView: View { @StateObject private var viewModel = Container.shared.authViewModel() var body: some View { // ... } } 

Для сервисов без UI — через @Injected:

class PaymentService { @Injected(\.apiClient) private var api } 

Какие scope выбрать для зависимостей?

Factory поддерживает четыре scope:

Scope Поведение Когда использовать
.singleton Один экземпляр на всё приложение APIClient, кэш, логгер
.cached Один экземпляр до явного сброса Сессионные данные, токены
.shared Сильная ссылка; освобождается при отсутствии ссылок ViewModel для тяжёлых экранов
unique (default) Новый объект при каждом запросе Transient-объекты, DTO

Какой scope выбрать? Если зависимость живёт всё время работы приложения — .singleton. Если нужно сбросить состояние при logout — .cached. Для ViewModel, которые загружают данные и не должны висеть в памяти вечно, идеален .shared. В одном из проектов мы сократили потребление памяти на 40%, заменив .singleton на .shared для ViewModel статей.

Что делать, если ViewModel пересоздаётся?

Типичная ошибка: использование @ObservedObject вместо @StateObject при создании ViewModel через Factory. @StateObject создаёт объект один раз при первом рендере. Если же применить @ObservedObject, ViewModel будет пересоздаваться при каждом обновлении View — состояние теряется. Правило: @StateObject для создания (через Container.shared), @ObservedObject для передачи уже созданной ViewModel через init. Это одна из самых частых проблем, которые мы исправляем при внедрении DI.

Тестирование с Factory

Factory упрощает тестирование до предела. В setUp тест-кейса переопределяем регистрацию:

Container.shared.authRepository.register { MockAuthRepository(shouldSucceed: true) } 

После теста сбрасываем:

Container.shared.reset() 

Не нужен отдельный test-контейнер или моки через протоколы. Мы используем этот подход в более чем 30 проектах — он стабильно сокращает время настройки тестов на 50%.

Что входит в работу

  • Анализ текущей архитектуры и выявление связей между модулями.
  • Проектирование контрактов зависимостей и выбор scope для каждого типа.
  • Создание Container и перенос инициализации объектов в фабрики.
  • Интеграция @Injected для сервисного слоя и @StateObject + Factory для ViewModel.
  • Написание unit-тестов с переопределёнными регистрациями.
  • Документация по расширению контейнера.

Сроки

2–3 дня для типового SwiftUI-проекта (включая рефакторинг, если код уже написан без DI). Стоимость рассчитывается индивидуально — запросите оценку для вашего проекта.

Как мы работаем

  1. Анализ: изучаем код, выявляем существующие связи и болевые точки.
  2. Проектирование: определяем границы модулей, выбираем scope.
  3. Реализация: создаём Container, переносим инициализацию.
  4. Тестирование: покрываем ключевые сценарии unit-тестами.
  5. Деплой: документируем процесс и передаём проект.

Наши инженеры имеют 7+ лет опыта в iOS-разработке и сертификаты Apple. Получите консультацию — оценим ваш проект бесплатно. Закажите внедрение DI, и ваше приложение станет тестируемым, поддерживаемым и готовым к масштабированию.

Factory на GitHub: Factory