Реактивное программирование — это парадигма программирования, ориентированная на потоки данных и распространение изменений. В iOS-контексте это означает:
import Combine
class ViewModel {
@Published var username: String = ""
private var cancellables = Set<AnyCancellable>()
func setupBindings() {
$username
.debounce(for: .seconds(0.5), scheduler: RunLoop.main)
.sink { [weak self] name in
self?.validate(username: name)
}
.store(in: &cancellables)
}
}
import RxSwift
class SearchService {
let searchQuery = PublishSubject<String>()
private let disposeBag = DisposeBag()
init() {
searchQuery
.debounce(.milliseconds(300), scheduler: MainScheduler.instance)
.distinctUntilChanged()
.flatMapLatest { query in
return self.searchAPI(query)
}
.subscribe(onNext: { results in
print("Received results: \(results)")
})
.disposed(by: disposeBag)
}
}
// Combine пример
searchTextField.publisher(for: .editingChanged)
.map { $0.text ?? "" }
.filter { $0.count > 2 }
.sink { [weak self] query in
self?.search(query: query)
}
// RxSwift пример
func fetchUser(id: Int) -> Observable<User> {
return URLSession.shared.rx
.data(request: userRequest(id: id))
.map { try JSONDecoder().decode(User.self, from: $0) }
.retry(3)
}
// Совместное использование Combine и SwiftUI
class AppState: ObservableObject {
@Published var isLoggedIn: Bool = false
@Published var userProfile: UserProfile?
}
Упрощение асинхронного кода:
Эффективное управление состоянием:
Отзывчивый UI:
Тестируемость:
Кривая обучения:
Управление памятью:
// Важно не забывать отменять подписки
var cancellables = Set<AnyCancellable>()
func riskyMethod() {
NotificationCenter.default.publisher(for: UIApplication.willResignActiveNotification)
.sink { _ in print("App will resign active") }
// Утечка памяти без .store(in: &cancellables)
}
Избыточность для простых задач:
// Валидация формы в реальном времени
Publishers.CombineLatest3($email, $password, $acceptTerms)
.map { email, password, accepted in
return email.contains("@") && password.count >= 8 && accepted
}
.assign(to: \.isValid, on: self)
.store(in: &cancellables)
scrollView.publisher(for: \.contentOffset)
.filter { [weak self] _ in
self?.isNearBottom() == true
}
.throttle(for: .seconds(1), scheduler: DispatchQueue.main, latest: true)
.sink { [weak self] _ in
self?.loadNextPage()
}
.store(in: &cancellables)
// Обновление UI при изменениях в CoreData
NSManagedObjectContext.didChangeObjectsPublisher
.filter { $0.contains(where: { $0 is Post }) }
.receive(on: DispatchQueue.main)
.sink { [weak self] _ in
self?.refreshUI()
}
.store(in: &cancellables)
Хорошие кандидаты:
Плохие кандидаты:
Реактивное программирование в iOS — это мощный инструмент для:
Основные технологии:
Ключевые преимущества:
Важно:
Реактивный подход особенно полезен в современных iOS приложениях с интенсивным data flow и сложной бизнес-логикой.