Налаштування архітектури VIPER для iOS-додатку

TRUETECH займається розробкою, підтримкою та обслуговуванням мобільних додатків iOS, Android, PWA. Маємо великий досвід та експертизу для публікації мобільних додатків до популярних маркетів Google Play, App Store, Amazon, AppGallery та інші.

Розробка та підтримка будь-яких видів мобільних додатків:

Інформаційні та розважальні мобільні програми
Новинки, ігри, довідники, онлайн-каталоги, погодні, фітнес та здоров'я, туристичні, освітні, соціальні мережі та месенджери, квіз, блоги та подкасти, форуми, агрегатори
Мобільні програми електронної комерції
Інтернет-магазини, B2B-додатки, маркетплейси, онлайн-обмінники, кешбек-сервіси, біржі, дропшиппінг-платформи, програми лояльності, доставка їжі та товарів, платіжні системи
Мобільні програми для управління бізнес-процесами
CRM-системи, ERP-системи, управління проектами, інструменти для команди продажів, облік фінансів, управління виробництвом, логістика та доставка, управління персоналом, системи моніторингу даних
Мобільні програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, платформи надання електронних послуг, платформи кешбеку, відеохостинги, тематичні портали, платформи онлайн-бронювання та запису, платформи онлайн-торгівлі

Це лише деякі з типів мобільних додатків, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Послуги, які ми пропонуємо
Показано 1 з 1Усі 1735 послуг
Налаштування архітектури VIPER для iOS-додатку
Складний
~3-5 днів
Часті запитання

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

Етапи розробки

Останні роботи

  • image_mobile-applications_feedme_467_0.webp
    Розробка мобільного додатка для компанії FEEDME
    792
  • image_mobile-applications_xoomer_471_0.webp
    Розробка мобільного додатку для компанії XOOMER
    671
  • image_mobile-applications_rhl_428_0.webp
    Розробка мобільного додатку для компанії RHL
    1097
  • image_mobile-applications_zippy_411_0.webp
    Розробка мобільного додатку для компанії ZIPPY
    969
  • image_mobile-applications_affhome_429_0.webp
    Розробка мобільного додатку для компанії Affhome
    914
  • image_mobile-applications_flavors_409_0.webp
    Розробка мобільного додатку для компанії FLAVORS
    495

Настройка архітектури VIPER для iOS-застосунку

VIPER — найдеталізованіша з архітектур для iOS. View, Interactor, Presenter, Entity, Router — п'ять компонентів на один екран. У невеликих командах на це дивляться зі скепсисом: багато файлів, багато протоколів, багато коду. У командах 5+ осіб, що працюють над одним UIKit-застосунком, VIPER стає конкурентною перевагою: ізольовані модулі не конфліктують у git, Interactor тестується без UI, Router інкапсулює навігацію.

Анатомія VIPER-модуля

Один екран = один VIPER-модуль. Для екрана профіля:

ProfileModule/
    ProfileView.swift          // UIViewController, реалізує ProfileViewProtocol
    ProfilePresenter.swift     // логіка представлення, реалізує ProfilePresenterProtocol
    ProfileInteractor.swift    // бізнес-логіка та робота з даними
    ProfileRouter.swift        // навігація, реалізує ProfileRouterProtocol
    ProfileAssembly.swift      // фабрика, збирає модуль та ін'єктує залежності
    Protocols/
        ProfileProtocols.swift // всі протоколи модуля в одному файлі

Протоколи — основа VIPER:

// View ← Presenter
protocol ProfileViewProtocol: AnyObject {
    func displayUser(_ viewModel: ProfileViewModel)
    func displayError(_ message: String)
    func setLoading(_ loading: Bool)
}

// Presenter ← View
protocol ProfileViewToPresenterProtocol: AnyObject {
    func viewDidLoad()
    func editButtonTapped()
    func settingsTapped()
}

// Presenter ← Interactor
protocol ProfileInteractorOutputProtocol: AnyObject {
    func didFetchUser(_ user: User)
    func didFailFetchUser(_ error: Error)
}

// Interactor ← Presenter
protocol ProfileInteractorInputProtocol: AnyObject {
    func fetchUser()
}

// Router ← Presenter
protocol ProfileRouterProtocol: AnyObject {
    func navigateToEditProfile(user: User)
    func navigateToSettings()
}

Це багато коду. Саме тому для VIPER створюють Xcode-шаблони або генератори (Generamba, Vipergen) — один шаблон, команда generate profile створює всі 7 файлів з базовим кодом.

Interactor — серце бізнес-логіки

Interactor — єдине місце, де живе бізнес-логіка. Він не знає про UIKit, не знає про конкретне сховище:

final class ProfileInteractor {
    weak var presenter: ProfileInteractorOutputProtocol?
    private let userRepository: UserRepositoryProtocol

    init(userRepository: UserRepositoryProtocol) {
        self.userRepository = userRepository
    }
}

extension ProfileInteractor: ProfileInteractorInputProtocol {
    func fetchUser() {
        Task {
            do {
                let user = try await userRepository.fetchCurrentUser()
                await MainActor.run {
                    presenter?.didFetchUser(user)
                }
            } catch {
                await MainActor.run {
                    presenter?.didFailFetchUser(error)
                }
            }
        }
    }
}

Тестування Interactor: підміняємо UserRepositoryProtocol моком — чистий Swift, XCTest без симулятора. Це те, ради чого варто платити вартість boilerplate.

Presenter: трансформація даних

Presenter отримує доменні Entity від Interactor та створює ViewModel для View:

extension ProfilePresenter: ProfileInteractorOutputProtocol {
    func didFetchUser(_ user: User) {
        let viewModel = ProfileViewModel(
            displayName: "\(user.firstName) \(user.lastName)",
            avatarURL: user.avatarURL,
            memberSince: DateFormatter.mediumStyle.string(from: user.createdAt),
            isVerified: user.verificationStatus == .verified
        )
        view?.displayUser(viewModel)
        view?.setLoading(false)
    }
}

ProfileViewModel — структура з UI-даними, не доменна User. View отримує готові рядки, не займається форматуванням.

Assembly: збірка модуля

Вся ініціалізація та DI — в Assembly:

enum ProfileAssembly {
    static func build(coordinator: AppCoordinator) -> UIViewController {
        let interactor = ProfileInteractor(
            userRepository: DI.resolve(UserRepositoryProtocol.self)
        )
        let router = ProfileRouter(coordinator: coordinator)
        let presenter = ProfilePresenter(interactor: interactor, router: router)
        let view = ProfileViewController()

        view.presenter = presenter
        presenter.view = view
        interactor.presenter = presenter

        return view
    }
}

Вся граф залежностей модуля видна в одному файлі. При додаванні нової залежності — тільки Assembly змінюється, решта компоненти ізольовані.

Генератори коду

Писати VIPER вручну — дуже дорого по часу. Інструменти:

  • Generamba — Ruby gem, шаблони через YAML, інтеграція в Xcode з командою generamba gen ProfileModule viper
  • XcodeGen з кастомними шаблонами
  • Swift Package з Makefile — власний генератор на основі Stencil-шаблонів

На проектах з 30+ модулями без генератора VIPER перетворюється в біль.

VIPER vs Clean Architecture + MVVM

VIPER органічен для UIKit + Objective-C legacy або великих команд з усталеними процесами. Для нових проектів на SwiftUI Clean Architecture + MVVM + @Observable — чистіше та без boilerplate. Для Flutter — BLoC з Clean Architecture ближе до VIPER за ідеологією, але без UIKit-залежностей.

Вибір на користь VIPER обґрунтований, якщо:

  • Існуючий проект уже на VIPER (рефакторити нема сенсу)
  • Команда 5+ iOS-розробників, активний паралельний код
  • Високі вимоги до тестованості кожного шару

Що настраюємо

Проектуємо протоколи → створюємо Xcode-шаблон або настраюємо Generamba → реалізуємо базовий VIPER-модуль з тестами як образец → документуємо правила для команди → при необхідності мігруємо пріоритетні MVC/MVP-екрани.

Робота займає 3–5 днів для нового проекту, включаючи генератор та документацію. Вартість розраховується після аналізу кількості модулів та складу команди.