Ответ
Для картографического приложения рекомендуется MVVM + Clean Architecture (слоистая архитектура).
Почему такая комбинация?
- MVVM идеально подходит для UI, интенсивно работающего с данными (карты, маркеры, анимации). ViewModel управляет состоянием карты и преобразует сырые геоданные для отображения.
- Clean Architecture разделяет ответственность на слои, что критично для работы с внешними SDK (MapKit, Google Maps) и сложной доменной логикой (построение маршрутов, геокодирование).
Предлагаемая структура слоев:
// 1. Domain Layer (Бизнес-логика, независима от iOS/SDK)
protocol RouteCalculator {
func calculateRoute(from: Location, to: Location) async throws -> Route
}
struct Location {
let latitude: Double
let longitude: Double
}
// 2. Data Layer (Реализация доменных протоколов, работа с SDK и сетью)
import MapKit
class MapKitRouteService: RouteCalculator {
func calculateRoute(from: Location, to: Location) async throws -> Route {
// Использование MapKit/MKDirections
let request = MKDirections.Request()
// ... настройка запроса
let directions = MKDirections(request: request)
let response = try await directions.calculate()
// Преобразование ответа MapKit в доменную модель Route
return Route(from: response)
}
}
// 3. Presentation Layer (MVVM)
class MapViewModel: ObservableObject {
@Published var annotations: [Annotation] = []
@Published var selectedRoute: Route?
private let routeCalculator: RouteCalculator
init(routeCalculator: RouteCalculator) {
self.routeCalculator = routeCalculator
}
func findRoute(from: Location, to: Location) async {
do {
let route = try await routeCalculator.calculateRoute(from: from, to: to)
await MainActor.run { self.selectedRoute = route }
} catch {
// Обработка ошибки
}
}
}
// View (SwiftUI пример)
struct MapView: View {
@StateObject var viewModel: MapViewModel
var body: some View {
Map {
// Отрисовка маркеров из viewModel.annotations
// Отрисовка полилинии из viewModel.selectedRoute
}
.task { await viewModel.findRoute(...) }
}
}
Ключевые преимущества:
- Смена картографического SDK: Чтобы заменить MapKit на Google Maps, нужно изменить только
Data Layer(реализациюRouteCalculator), Domain и Presentation слои остаются нетронутыми. - Тестируемость: Доменную логику (
RouteCalculator) и логику представления (MapViewModel) можно тестировать юнит-тестами с моками, без запуска симулятора. - Масштабируемость: Новые функции (поиск POI, оффлайн-карты) добавляются как новые доменные протоколы и сервисы.
Дополнительный компонент: Координатор (Router) для управления навигацией между экранами карты, поиска и детальной информации.