Ответ
Driver — специальный тип Observable в RxSwift с гарантиями:
- Не вызывает ошибок (error events)
- Выполняется на главном потоке (MainScheduler)
- Share side effects (share(replay: 1, scope: .whileConnected))
Создание Driver:
// Из Observable
let observable = Observable<String>.create { observer in
observer.onNext("Data")
observer.onCompleted()
return Disposables.create()
}
let driver = observable
.asDriver(onErrorJustReturn: "Fallback Value")
// Из Subject
let subject = PublishSubject<String>()
let driverFromSubject = subject.asDriver(onErrorJustReturn: "Error")
// С помощью Driver.create
let customDriver = Driver<String>.create { observer in
observer.onNext("Initial")
observer.onCompleted()
return Disposables.create()
}
Подписка на Driver:
Используйте drive() вместо subscribe():
// Базовый вариант
driver
.drive(onNext: { value in
print("Received: (value)") // Гарантированно на главном потоке
self.label.text = value // Безопасно для UI
})
.disposed(by: disposeBag)
// Привязка к UI элементам
driver
.drive(label.rx.text) // Автоматическая привязка
.disposed(by: disposeBag)
// Обработка нескольких подписчиков
driver
.drive(onNext: { value in
updateView1(value)
})
.disposed(by: disposeBag)
driver // Тот же Driver, side effects shared
.drive(onNext: { value in
updateView2(value)
})
.disposed(by: disposeBag)
Обработка ошибок в Driver:
// 1. Замена ошибки дефолтным значением
observable
.asDriver(onErrorJustReturn: "Default")
// 2. Recovery с другого Observable
observable
.asDriver(onErrorRecover: { error in
return backupObservable.asDriver(onErrorJustReturn: "Backup")
})
// 3. Игнорирование ошибок
observable
.asDriver(onErrorDriveWith: .empty())
Операторы для Driver:
// Все стандартные операторы + специальные
let processedDriver = driver
.map { $0.uppercased() } // Transform
.filter { !$0.isEmpty } // Filter
.debounce(.milliseconds(300)) // Throttle
.distinctUntilChanged() // Unique values
.flatMapLatest { query in // Latest async
searchAPI(query)
.asDriver(onErrorJustReturn: [])
}
Практический пример — поиск:
searchTextField.rx.text.orEmpty
.asDriver() // Конвертация в Driver
.debounce(.milliseconds(500))
.distinctUntilChanged()
.flatMapLatest { query in
return apiService.search(query)
.asDriver(onErrorJustReturn: []) // Ошибки → пустой массив
}
.drive(tableView.rx.items(cellIdentifier: "Cell")) { index, item, cell in
cell.configure(with: item)
}
.disposed(by: disposeBag)
| Ключевые отличия от Observable: | Аспект | Driver | Observable |
|---|---|---|---|
| Поток | MainScheduler | Любой | |
| Ошибки | Не может emit error | Может emit error | |
| Side effects | Shared | Могут повторяться | |
| Использование | UI-биндинг | Общие операции |
Важно: Всегда используйте Driver для привязки к UI-элементам для гарантии работы на главном потоке и корректной обработки ошибок.