Можно ли использовать архитектуру VIPER со SwiftUI?

Ответ

Да, можно адаптировать, но это требует переосмысления некоторых компонентов, так как SwiftUI основан на декларативном и реактивном подходе.

Адаптация компонентов VIPER для SwiftUI:

Компонент Роль в SwiftUI Реализация
View Декларативное описание UI. SwiftUI View. Получает данные от Presenter через @ObservedObject или @StateObject.
Presenter Преобразует данные от Interactor для View, обрабатывает действия пользователя. Класс, наследующий ObservableObject. Содержит @Published свойства.
Interactor Содержит бизнес-логику, работу с сетью и данными. Обычный класс, как в UIKit.
Entity Модели данных. Без изменений (структуры).
Router Управление навигацией и сборкой модулей. Адаптируется под NavigationStack, модификаторы .sheet и т.д. Часто реализуется как координатор.

Пример связи View и Presenter:

// VIEW
struct ArticleListView: View {
    @StateObject var presenter: ArticleListPresenter // Presenter как StateObject

    var body: some View {
        List(presenter.articles) { article in
            Text(article.title)
                .onTapGesture { presenter.didSelect(article) }
        }
        .onAppear { presenter.viewDidAppear() }
    }
}

// PRESENTER
class ArticleListPresenter: ObservableObject {
    @Published var articles: [Article] = []
    let interactor: ArticleListInteractorProtocol
    let router: ArticleListRouterProtocol

    func viewDidAppear() {
        articles = interactor.fetchArticles()
    }

    func didSelect(_ article: Article) {
        router.showDetails(for: article)
    }
}

Вывод: VIPER в SwiftUI возможен, но часто считается избыточным. Более естественными являются паттерны MVVM или Model-View.

Ответ 18+ 🔞

О, слушай, смотри, блядь, про VIPER в SwiftUI! Ну, типа, да, можно, конечно, запихнуть эту архаичную, блядь, конструкцию в декларативный рай, но это будет как впихнуть невпихуемое, ёпта. Придётся всё переосмысливать, потому что SwiftUI — он другой, реактивный, блядь, а не императивный, как старый добрый UIKit.

Как эту хуйню адаптировать под SwiftUI, блядь:

Компонент Роль в SwiftUI Что делать, сука
View Это просто описание, блядь, что рисовать. Обычный SwiftUI View. Тычется в Presenter через @ObservedObject или @StateObject.
Presenter Переводит с языка бизнес-логики на человеческий, обрабатывает тапы. Класс, который наследуется от ObservableObject. Там внутри @Published свойства, которые View подписывает.
Interactor Тут вся грязная работа: сетевые запросы, базы данных, пиздец. Обычный класс, как и был. Ничего особенного.
Entity Модельки, данные. Структуры, без изменений, блядь.
Router Навигация, переходы, сборка модулей. Адаптируется под NavigationStack, .sheet и прочую хуйню. Часто делают какого-нибудь координатора, чтобы не мозолил глаза.

Вот, смотри, как View и Presenter друг на друга смотрят, блядь:

// VIEW (ЭТОТ КОД НЕ ТРОГАТЬ, БЛЯДЬ!)
struct ArticleListView: View {
    @StateObject var presenter: ArticleListPresenter // Presenter как StateObject

    var body: some View {
        List(presenter.articles) { article in
            Text(article.title)
                .onTapGesture { presenter.didSelect(article) }
        }
        .onAppear { presenter.viewDidAppear() }
    }
}

// PRESENTER
class ArticleListPresenter: ObservableObject {
    @Published var articles: [Article] = [] // Вот за этим View следит, как ястреб
    let interactor: ArticleListInteractorProtocol
    let router: ArticleListRouterProtocol

    func viewDidAppear() {
        // Пошёл, сука, Interactor, работай!
        articles = interactor.fetchArticles()
    }

    func didSelect(_ article: Article) {
        // Router, веди нас, блядь, куда надо!
        router.showDetails(for: article)
    }
}

Вывод, ёпта: VIPER в SwiftUI — это как ехать на телеге с квадратными колёсами по автобану. Вроде доедешь, но все будут охуевать. Чаще для SwiftUI берут MVVM или просто Model-View, там проще и естественнее, блядь. Но если ты упоротый архитектурный маньяк — дерзай, хуле.