Проблема в том, что CombineLatest
не принимает замыкание, оно просто испускает последнее значение, испускаемое всеми его восходящими потоками всякий раз, когда какой-либо из восходящих потоков испускает новое значение. Вместо этого ваше закрытие должно быть передано compactMap
, то есть оператору, который принимает закрытие, возвращающее Optional
, и выдает значение ниже по потоку, если возвращаемое значение не было nil
.
struct CustomerUpdates {
@Published var photo: UIImage!
@Published var firstName: String!
@Published var lastName: String!
@Published var id: String!
typealias CustomerTuple = (photo: UIImage, firstName: String, lastName: String, id: String)
var validatedCustomer: AnyPublisher<CustomerTuple, Never> {
return Publishers.CombineLatest4($photo, $firstName, $lastName, $id)
.compactMap { photo, firstName, lastName, id in
guard let photo = photo, let firstName = firstName, let lastName = lastName, let id = id else { return nil }
return ( photo, firstName, lastName, id)
}
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
}
}
A пара других вопросов, не связанных с вашим вопросом: такого оператора return(on:)
нет, вам нужно receive(on:)
и вы хотите передать DispatchQueue.main
, а не RunLoop.main
, чтобы иметь возможность публиковать sh обновления прямо в вашем пользовательском интерфейсе.
Имена типов должны быть UpperCamelCase в Swift, поэтому используйте CustomerTuple
вместо customerTuple
.
Кроме того, ваши свойства должны быть Optional
(var photo: UIImage?
), а не неявно развернуты необязательно ( var photo: UIImage!
).