RxSwift подписка внутри проблемы блока завершения - PullRequest
0 голосов
/ 24 сентября 2018

У меня настоящая специфическая проблема.Я обычно получал это, и я не мог найти почему.

Основная проблема, хотя я использую disposeBag некоторые из моих вызовов «subscribe (onNext:» »несколько раз. Но я нашел кое-что; число вызовов увеличилось линейнозависит от другой подписки.

Например, у меня есть два компонента, объявленных в viewController. Один, если это настраиваемое представление коллекции, а другой - настраиваемый менеджер управления обновлением.

self.kpiesCollectionView.collectionHeaderButton.rx.tap
    . subscribe(onNext: { [weak self] _ in
           // Push to next ViewController
       }).disposed(by: self.kpiesCollectionView.disposeBag)


refreshControl.rx.controlEvent(UIControlEvents.valueChanged).asObservable().subscribe(onNext: { () in
            DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 2) {
                completion()
            }
        }).disposed(by: disposeBag)

Работа refreshControl обрабатывается самостоятельно. Она просто возвращает завершение viewController. Поэтому я вызываю disposeBag для себя.

И сценарий выглядит следующим образом:

Нажмите кнопку -> Pushes to VC (1 раз)

Pull-To-RefreshНажмите кнопку -> Толкает к VC (2 раза)

Pull-To-RefreshНажмите кнопку -> толкает в ВК (3 раза)

Обновлено

Я обнаружил проблему.Именно поэтому я тоже обновил заголовок.Причина в том, что я использовал self.kpiesCollectionView.collectionHeaderButton.rx.tap.subscribe( в своем блоке завершения запроса, но когда я перешел за его пределы, это сработало хорошо.

Возможно, это было не то место, но я просто хочу узнать.Как я могу избежать этого?Как я могу вызвать подписку () даже внутри блока?

1 Ответ

0 голосов
/ 24 сентября 2018

Я решил опубликовать ответ здесь, может быть, другой пользователь SO найдет его полезным.Таким образом, если ваш код в subscribe:onNext вызывается несколько раз, а наблюдатель не отправил команду onNext, это означает, что вы подписались несколько раз на наблюдателя.

Теперь dispose(bag:) будет удалять любых подписчиков, когдасумка утилизации освобождается, но если сумка все еще находится на вашем объекте, абонент не будет освобожден, более того, в случае подписчиков пользовательского интерфейса (в контроллерах представлений, представлениях и т. д.) рекомендуется использовать week selfвнутри onNext:/onError/etc, чтобы избежать циклов сохранения вашей сумки / контроллера.

Чтобы «принудительно» утилизировать сумку, у вас есть три варианта:

  • , если вы используете DisposeBag, этодостаточно для повторной инициализации пакета (bag = DisposeBag()).
  • существует CompositeDisposable, который работает как словарь, этот тип пакета дает вам более точный контроль над тем, что вы можете распоряжаться, всякий раз, когда вы добавляете одноразовый пакетв сумке (bag.insert, вы получите ключ для этого одноразового использования, и вы можете позвонить remove с помощью этого ключа;
  • последний вариант, иногда более похожий на уродливый вариант, заключается всохранить ссылкудоступ к одноразовому и вызовите распоряжение непосредственно на нем, что-то вроде:

    var myDisposable: Disposable? = nil
    
    ......
    fun iWantToSubscribe() {
        myDispsable?.dispose()
        myDisposable = myObserver.subscribe(onNext: {})
    }
    
...