Подписаться возвращая Void вместо AnyCancelable - PullRequest
0 голосов
/ 04 июля 2019

В настоящее время у меня есть издатель с типом AnyPublisher<[MyClass], Error>, к которому я пытаюсь подключить подписчика и получить полученный AnyCancelable.Автозаполнение XCode говорит, что я должен быть в состоянии сделать это, но когда код фактически введен, я сталкиваюсь с ошибкой компилятора, говорящей, что возвращаемый тип не AnyCancelable, а ()

Вот примермой код:

let networkController = NetworkController()
let viewState = MyViewState()

let publisher: AnyPublisher<[MyClass], Error> = networkController.createPublisher()
let cancelable: AnyCancellable = publisher.subscribe(viewState)
Cannot convert value of type '()' to specified type 'AnyCancellable'

Моя цель состоит в том, чтобы обернуть существующую асинхронную функцию, которую можно вызывать много раз, в Combine Framework, чтобы у меня был хороший способ отменить запрос, когдаон переназначен, вот так:

... self.cancelable = cancelable

1 Ответ

0 голосов
/ 05 июля 2019

AnyPublisher имеет два subscribe метода для прикрепления Subscriber к Publisher. Он наследует оба из протокола Publisher. Вот они:

func subscribe<S>(_ subscriber: S)
    where S : Subscriber, Self.Failure == S.Failure, Self.Output == S.Input

func subscribe<S>(_ subject: S) -> AnyCancellable
    where S : Subject, Self.Failure == S.Failure, Self.Output == S.Output

Итак, я думаю, ваш тип MyViewState не соответствует протоколу Subject. Поэтому вы не можете использовать версию subscribe, которая возвращает AnyCancellable.

Subject - это субпротокол Publisher, который предоставляет send методы для ввода значений, которые затем публикует Subject. Вы хотите, чтобы ваш MyViewState класс был Publisher? Я подозреваю, что нет.

Вместо этого вы, вероятно, захотите изменить тип MyViewState, чтобы он не соответствовал Subscriber. Вместо этого используйте метод AnyPublisher sink (также унаследованный от Publisher), чтобы подключить издателя к вашему viewState. Метод sink возвращает объект Sink, который соответствует Cancellable:

func sink(
    receiveCompletion: ((Subscribers.Completion<Failure>) -> Void)? = nil,
    receiveValue: @escaping ((Output) -> Void))
    -> Subscribers.Sink<Output, Failure>

При необходимости вы можете обернуть возвращенные Cancellable в AnyCancellable. Таким образом:

let can = publisher.sink(
    receiveCompletion: { viewModel.receive(completion: $0) },
    receiveValue: { viewModel.receive($0) })
let anyCan = AnyCancellable(can)
...