Какую архитектуру выбрать для нового iOS-проекта?

«Какую архитектуру выбрать для нового iOS-проекта?» — вопрос из категории Архитектура, который задают на 10% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Для большинства новых iOS-проектов оптимальным выбором будет MVVM (Model-View-ViewModel) в связке с Координатором (Coordinator).

Почему MVVM?

  • Четкое разделение ответственности:
    • Model: Данные и бизнес-логика.
    • View (ViewController/UIView): Отображение UI и обработка пользовательских действий.
    • ViewModel: Преобразование данных Model для View, обработка логики представления.
  • Идеально для реактивного программирования: ViewModel легко публикует данные через @Published (Combine) или ObservableObject (SwiftUI), на которые реагирует View.
  • Высокая тестируемость: Логика в ViewModel легко тестируется без UIKit.

Зачем Coordinator?

  • Выносит логику навигации из ViewController'ов.
  • Делает поток экранов явным, переиспользуемым и тестируемым.

Базовый пример на UIKit + Combine:

// Model
struct User { let name: String }

// ViewModel
class UserViewModel {
    @Published var userName: String = ""
    private let userService: UserService

    init(service: UserService) {
        self.userService = service
    }

    func loadUser() {
        // Бизнес-логика
        userService.fetchUser { [weak self] user in
            self?.userName = user.name
        }
    }
}

// View
class UserViewController: UIViewController {
    private let viewModel: UserViewModel
    private var cancellables = Set<AnyCancellable>()
    @IBOutlet private var nameLabel: UILabel!

    init(viewModel: UserViewModel) {
        self.viewModel = viewModel
        super.init(nibName: nil, bundle: nil)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        // Подписка на изменения в ViewModel
        viewModel.$userName
            .receive(on: DispatchQueue.main)
            .assign(to: .text, on: nameLabel)
            .store(in: &cancellables)
        viewModel.loadUser()
    }
}

Альтернативы:

  • SwiftUI + Combine: Предпочтительный стек для проектов, таргетирующих iOS 14+.
  • VIPER/Clean Swift: Для очень крупных, сложных проектов с большими командами, где важна максимальная модульность и тестируемость (но добавляют boilerplate-код).