Генератор DataTaskPublisher: каким будет правильный тип возвращаемой функции?

#ios #combine

#iOS #объединить

Вопрос:

Цель: я хочу создать генератор dataTaskPublisher, к которому может получить доступ любой подписчик.

Я хотел бы создать функцию, которая возвращает издателя для использования подписчиком общего назначения. Что-то вроде:

 let remoteDataPublisher = generatedPublisher(url: <http://....>) 
 

Вот что я представляю для функции:

 struct model: Codable {
}
    
func generalPublisher(url: URL) -> URLSession.DataTaskPublisher  {
        let remoteDataPublisher = URLSession.shared.dataTaskPublisher(for: url)
                        .map(.data)
                        .receive(on: DispatchQueue.main)
                        .decode(type: model.self, decoder: JSONDecoder())

         return remoteDataPublisher

    }
 

Вот подписчик:

 remoteDataPublisher
                    .eraseToAnyPublisher()
                    .sink(receiveCompletion: { completion in
                        switch completion {
                        case .finished:
                            print("Publisher Finished")
                        case let .failure(anError):
                            Swift.print("n(GovernmentCountryDataList: (country) Received error: #function", anError)
                        }
                    }, receiveValue: { someValue in
                        SingletonData.shared.governmentCountryDataList = someValue
                        print("GovernmentCountryDataList: (country)")
                        print(SingletonData.shared.governmentCountryDataList ?? "No Data for (country)")
                        NotificationCenter.default.post(name: NSNotification.Name(rawValue: "noteName"), object: DataModelType.GovernmentCountryDataList(country: country))
                    }).store(in: amp;cancellables)
 

Вот ошибка компилятора:

введите описание изображения здесь

Вопрос: Каков правильный синтаксис / тип данных возвращаемого значения функции?
Как исправить?

Ответ №1:

Вы сопоставляете DataTaskPublisher издателю вашего Model типа, поэтому я бы предложил соответствующим образом изменить возвращаемый тип (и eraseToAnyPublisher здесь):

 struct Model: Codable { ... }

func generalPublisher(for url: URL) -> AnyPublisher<Model, Error> {
    URLSession.shared.dataTaskPublisher(for: url)
        .map(.data)
        .decode(type: Model.self, decoder: JSONDecoder())
        .receive(on: DispatchQueue.main)
        .eraseToAnyPublisher()
}
 

FWIW, я бы предложил начинать имена ваших типов с заглавной буквы, как правило.


Затем вы можете делать такие вещи, как:

 generalPublisher(for: url)
    .sink { completion in
        switch completion {
        case .finished:
            print("Publisher Finished")

        case let .failure(error):
            print("n(GovernmentCountryDataList: (country) Received error: #function", error)
        }
    } receiveValue: { value in
        SingletonData.shared.governmentCountryDataList = value
        print("GovernmentCountryDataList: (country)")
        print(SingletonData.shared.governmentCountryDataList ?? "No Data for (country)")
        NotificationCenter.default.post(name: NSNotification.Name(rawValue: "noteName"), object: DataModelType.GovernmentCountryDataList(country: country))
    }.store(in: amp;cancellables)