В iOS-разработке используется широкий спектр паттернов проектирования, которые можно разделить на три основные категории:
// Классический 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"
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
Используется для сложных экранов, где нужно четкое разделение ответственностей
class AppSettings {
static let shared = AppSettings()
private init() {}
var themeColor: UIColor = .systemBlue
}
Использование: Для глобальных настроек, менеджеров
protocol DataLoaderDelegate: AnyObject {
func dataDidLoad(_ data: Data)
}
class DataLoader {
weak var delegate: DataLoaderDelegate?
func load() {
// После загрузки:
delegate?.dataDidLoad(data)
}
}
Где применяется: UITableViewDelegate, UICollectionViewDelegate
NotificationCenter.default.addObserver(
self,
selector: #selector(handleNotification),
name: UIApplication.didBecomeActiveNotification,
object: nil
)
Альтернатива: Combine, RxSwift
protocol Theme {
var backgroundColor: UIColor { get }
}
class ThemeFactory {
static func makeTheme(for style: UIUserInterfaceStyle) -> Theme {
return style == .dark ? DarkTheme() : LightTheme()
}
}
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
Паттерн, при котором UI создается кодом без storyboards/xibs
class CustomView: UIView {
private let label = UILabel()
override init(frame: CGRect) {
super.init(frame: frame)
setupViews()
}
private func setupViews() {
addSubview(label)
// Констрейнты и настройка
}
}
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
}
struct ContentView: View {
@State private var isOn = false
var body: some View {
Toggle("Switch", isOn: $isOn)
.padding()
}
}
@Published var searchText: String = ""
$searchText
.debounce(for: .milliseconds(300), scheduler: RunLoop.main)
.sink { [weak self] text in
self?.filterResults(with: text)
}
.store(in: &cancellables)
В iOS-разработке используется богатый набор паттернов - от классических ООП-шаблонов до специализированных архитектурных подходов. Выбор зависит от конкретной задачи, масштаба проекта и опыта команды. Ключевой принцип - использовать паттерны как инструменты для решения проблем, а не как самоцель. Современная iOS-разработка все больше смещается в сторону реактивного и декларативного программирования, но фундаментальные принципы остаются актуальными.