Какие паттерны используются в iOS?ios-55

В iOS-разработке используется широкий спектр паттернов проектирования, которые можно разделить на три основные категории:

1. Основные архитектурные паттерны

MVC

// Классический Apple-подход
class UserModel {
    var name: String
}

class UserViewController: UIViewController {
    @IBOutlet weak var nameLabel: UILabel!
    var user: UserModel!

    override func viewDidLoad() {
        nameLabel.text = user.name
    }
}

Проблема: Часто превращается в "Massive View Controller"

MVVM

class UserViewModel {
    var userName: String { model.name.uppercased() }
    private let model: UserModel

    init(model: UserModel) {
        self.model = model
    }
}

class UserViewController: UIViewController {
    @IBOutlet weak var nameLabel: UILabel!
    var viewModel: UserViewModel!

    override func viewDidLoad() {
        nameLabel.text = viewModel.userName
    }
}

Преимущество: Лучшая разделяемость логики и UI

VIPER

Используется для сложных экранов, где нужно четкое разделение ответственностей

2. Паттерны проектирования

Singleton

class AppSettings {
    static let shared = AppSettings()
    private init() {}

    var themeColor: UIColor = .systemBlue
}

Использование: Для глобальных настроек, менеджеров

Delegate

protocol DataLoaderDelegate: AnyObject {
    func dataDidLoad(_ data: Data)
}

class DataLoader {
    weak var delegate: DataLoaderDelegate?

    func load() {
        // После загрузки:
        delegate?.dataDidLoad(data)
    }
}

Где применяется: UITableViewDelegate, UICollectionViewDelegate

Observer

NotificationCenter.default.addObserver(
    self,
    selector: #selector(handleNotification),
    name: UIApplication.didBecomeActiveNotification,
    object: nil
)

Альтернатива: Combine, RxSwift

Factory

protocol Theme {
    var backgroundColor: UIColor { get }
}

class ThemeFactory {
    static func makeTheme(for style: UIUserInterfaceStyle) -> Theme {
        return style == .dark ? DarkTheme() : LightTheme()
    }
}

3. Специфичные iOS-паттерны

Coordinator

class AppCoordinator {
    private let navigationController: UINavigationController

    init(navigationController: UINavigationController) {
        self.navigationController = navigationController
    }

    func showUserProfile(for user: User) {
        let vc = UserProfileViewController()
        vc.coordinator = self
        navigationController.pushViewController(vc, animated: true)
    }
}

Решает: Проблему навигации и зависимости между VC

View Code

Паттерн, при котором UI создается кодом без storyboards/xibs

class CustomView: UIView {
    private let label = UILabel()

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupViews()
    }

    private func setupViews() {
        addSubview(label)
        // Констрейнты и настройка
    }
}

DataSource

lazy var dataSource = UICollectionViewDiffableDataSource<Section, Item>(collectionView: collectionView) {
    collectionView, indexPath, item in
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath)
    cell.configure(with: item)
    return cell
}

4. Современные тенденции

Declarative UI

struct ContentView: View {
    @State private var isOn = false

    var body: some View {
        Toggle("Switch", isOn: $isOn)
            .padding()
    }
}

Reactive Programming

@Published var searchText: String = ""

$searchText
    .debounce(for: .milliseconds(300), scheduler: RunLoop.main)
    .sink { [weak self] text in
        self?.filterResults(with: text)
    }
    .store(in: &cancellables)

Критерии выбора паттерна

  1. Сложность фичи: Для простых - MVC, для сложных - MVVM/VIPER
  2. Команда: Есть ли опыт работы с реактивным программированием
  3. Поддержка: Нужна ли долгосрочная поддержка кода
  4. Тестируемость: Требуется ли покрытие unit-тестами

Распространенные ошибки

  1. Слепое следование модным паттернам
  2. Смешивание разных подходов без необходимости
  3. Переусложнение простых задач
  4. Игнорирование особенностей Apple-фреймворков

Резюмируем

В iOS-разработке используется богатый набор паттернов - от классических ООП-шаблонов до специализированных архитектурных подходов. Выбор зависит от конкретной задачи, масштаба проекта и опыта команды. Ключевой принцип - использовать паттерны как инструменты для решения проблем, а не как самоцель. Современная iOS-разработка все больше смещается в сторону реактивного и декларативного программирования, но фундаментальные принципы остаются актуальными.