#swift #combine
#swift #объединить
Вопрос:
Я новичок в combine и изо всех сил пытаюсь понять, как я могу вернуть результат моих выводов выборки.
Я могу установить результат как @Published
, но я хочу просто иметь возможность вызывать метод выборки и ожидать результата или ошибки.
class PinService: NSObject, ObservableObject {
private var session: Session
private var subscriptions = Set<AnyCancellable>()
init(session: Session) {
self.session = session
super.init()
}
func fetchPins (categories: Set<CategoryModel>, coordinates: CLLocationCoordinate2D) {
_fetchPins(categories: categories, coordinates: coordinates)
.sink(receiveCompletion: { completion in
switch completion {
case .failure:
print("fetchPins() error")
case .finished:
print("fetchPins() complete")
}
}, receiveValue: { pins in
/*
What to do here?
I can add a @Published var pins: [Pin], and do
self.pins = pins
But if I want to be able to return the value or the error, how can I do that?
*/
})
.store(in: amp;self.subscriptions)
}
private func _fetchPins(categories: Set<CategoryModel>, coordinates: CLLocationCoordinate2D) -> Future<[Pin], Error> {
return Future<[Pin], Error> { promise in
let categoryIds = categories.map { return $0.id }.joined(separator: ",")
let radius = 15 //miles
self.session.request(baseUrl "/api/v1/pinsRadius?latitude=(coordinates.latitude)amp;longitude=(coordinates.longitude)amp;radius=(radius)amp;categories=(categoryIds)")
.responseDecodable(of: [Pin].self) { (response: DataResponse) in
switch response.result {
case .success(let pins):
promise(.success((pins)))
case .failure(let error):
promise(.failure(error))
}
}
}
}
}
Извините, если это глупый вопрос, спасибо.
Ответ №1:
Одним из решений является использование обработчика завершения в вашей функции и вызов его из receiveValue
func fetchPins (categories: Set<CategoryModel>,
coordinates: CLLocationCoordinate2D,
completion: @escaping (Result<[Pin], Error>) -> Void)) {
_fetchPins(categories: categories, coordinates: coordinates)
.sink(receiveCompletion: { completion in
switch completion {
case .failure(let error):
completion(.failure(error))
print("fetchPins() error")
case .finished:
print("fetchPins() complete")
}
}, receiveValue: { pins in
completion(.success(pins))
})
.store(in: amp;self.subscriptions)
}
Тогда ваш вызов fetchPins
будет выглядеть примерно так
fetchPins(categories: someValue, coordinates: someOtherValue) { pins in
//do stuff with pins here
}
Комментарии:
1. Спасибо! Как я могу также отправить ошибку? У меня нет ошибки в блоке receiveValue.
2. Вы можете изменить тип параметра для обработчика завершения с [Instrument] на Result<[Instrument], Error>, а затем вызвать его с помощью .success или .failure
3. Какова цель
.store(in: amp;self.subscriptions)
, если контакты уже сохранены в завершении:completion(.success(pins)
?4. Сохраняется подписка
5. Хорошо, я понял. Так что это нужно только в том случае, если вы также хотите сохранить подписку помимо контактов (в этом примере) ?.