Ответ
Многие классы UIKit, созданные в эпоху MVC, демонстрируют нарушения SOLID из-за высокой связности и многофункциональности.
1. UIViewController — нарушение SRP (Принцип единственной ответственности)
- Проблема: «Massive View Controller» совмещает в себе:
- Управление жизненным циклом view.
- Бизнес-логику и обработку данных.
- Навигацию и логику переходов.
- Работу с делегатами таблиц/коллекций.
- Решение: Выделение ответственностей в отдельные объекты (Presenter, Interactor, Router, ViewModel).
2. UITableViewDataSource / UICollectionViewDataSource — нарушение OCP (Принцип открытости/закрытости)
- Проблема: Для изменения логики отображения ячеек (например, другой порядок секций) необходимо изменять код существующих методов
numberOfSections,cellForRowAt. - Решение: Использование архитектурных подходов (Compositional Layout, Diffable Data Source) или паттерна «Спецификация» для инкапсуляции логики секций и ячеек.
3. Неявные зависимости — нарушение DIP (Принцип инверсии зависимостей)
- Проблема: Прямое использование синглтонов и глобальных объектов.
class ProfileViewController: UIViewController { func saveUser() { // Нарушение DIP: прямая зависимость от конкретной реализации (CoreData) let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext // ... } } - Решение: Внедрение зависимости через протокол (интерфейс).
protocol DatabaseService { func save(user: User) }
class ProfileViewController { let database: DatabaseService // Зависимость от абстракции init(database: DatabaseService) { self.database = database } }
**4. Крупные делегаты — нарушение ISP (Принцип разделения интерфейсов)**
* **Проблема:** Протокол `UIScrollViewDelegate` содержит множество методов (`scrollViewDidScroll`, `scrollViewWillBeginDragging` и т.д.). Класс вынужден подписываться на весь протокол, даже если нужен один метод.
* **Решение:** Разделение на более мелкие протоколы (на практике достигается через необязательные методы в Objective-C, но логически проблема остаётся).