I have a published var called spotWallet in my BinanceStore class which conforms to observaleObject. I can create a publisher and subscribe to it. but there is property in my top level struct called balances which is an array of Balance struct. What I want to achieve is would like to update a property of Balance called price which comes from another network call. I cannot get that to work, in clean combine swiftui way.
class BinanceStore: ObservableObject, Identifiable {
@Published var spotWallet: SpotWallet?
@Published var loadingError: String = ""
@Published var showAlert: Bool = false
private var cancellableSet: Set<AnyCancellable> = []
private let binanceFetcher: BinanceFetchable
init(binanceFetcher: BinanceFetchable) {
self.binanceFetcher = binanceFetcher
}
func AccountDetailsOnSpot() async {
binanceFetcher.getAccountDetailsOnSpot()
.sink { (dataResponse) in
if dataResponse.error != nil {
self.createAlert(with: dataResponse.error!)
} else {
self.spotWallet = dataResponse.value!
}
}.store(in: &cancellableSet)
}
func createAlert( with error: NetworkError ) {
loadingError = error.localizedDescription
self.showAlert = true
}
}
struct SpotWallet: Codable, Hashable {
let makerCommission, takerCommission, buyerCommission, sellerCommission: Int
let canTrade, canWithdraw, canDeposit: Bool
let updateTime: Int
let accountType: String
let balances: [Balance]
let permissions: [String]
}
protocol BinanceFetchable {
func getAccountDetailsOnSpot() -> AnyPublisher<DataResponse<SpotWallet, NetworkError>, Never>
}
class BinanceFetcher {
var coinPublisher = PassthroughSubject<CoinBalance, Never>()
}
extension BinanceFetcher: BinanceFetchable {
func getAccountDetailsOnSpot() -> AnyPublisher<DataResponse<SpotWallet, NetworkError>, Never> {
let endpoint = "/api/v3/account"
let params = BinanceWrapper.shared.makeRequestReady(queries: nil)
let url = URL(string: "\(BinanceWrapper.BINANCE_BASE_URL)\(endpoint)")!
return AF.request(url, parameters: params, encoding: URLEncoding.default, headers: BinanceWrapper.BINANCE_HTTP_HEADERS)
.validate()
.publishDecodable(type: SpotWallet.self)
.map { response in
response.mapError { error in
return NetworkError.parsing(description: error.localizedDescription)
}
}
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
}
}