I have a code, that should match 2 JSON files and connect all data in one struct. I'm pretty sure that It works just fine, but I have faced very strange problem. I want to make a picker:
import SwiftUI
struct CurrencyView: View {
@ObservedObject var api = CurrencyViewModel()
@State private var pickerSelection1 = 1
var body: some View {
Text("f")
Picker("", selection: $pickerSelection1) {
ForEach(0..<self.api.currencies.fullName.count) { // Error here
let currency = api.currencies.fullName[$0] // and here
Text(currency)
}
}
.id(UUID())
.labelsHidden()
.padding(.leading)
}
}
struct CurrencyView_Previews: PreviewProvider {
static var previews: some View {
CurrencyView()
}
}
It shows this error:
Value of type '[Currency]' has no member 'fullName'
I know I'm missing smth and feel stupid, because I can't understand why. Thanks for the reply!)
Adding the rest of the code:
// Model
import Foundation
struct CurrencyModel: Codable {
var results: [String:Double]
}
struct CurrencyNewModel: Codable {
var currencies: [String:String]
}
struct Currency: Decodable {
let currencyCode: String
let fullName: String
var price: Double
}
// View Model
import SwiftUI
class CurrencyViewModel: ObservableObject {
@Published var currencies: [Currency] = []
init() {
fetchNewData { [self] (currency) in
switch currency {
case .success(let names):
print("Success")
DispatchQueue.main.async {
self.currencies = names.currencies.map {
Currency(currencyCode: $0.key, fullName: $0.value, price: 0)
}
}
fetchData { result in
switch result {
case .success(let prices):
print("Success")
for (index, value) in currencies.enumerated() {
if let price = prices.results.first(where: { $0.key == value.currencyCode }) {
DispatchQueue.main.async {
currencies[index].price = price.value
}
}
}
case .failure(let error):
print(error)
}
}
case .failure(let error):
print("Error", error)
}
}
}
func fetchData(completion: @escaping (Result<CurrencyModel,Error>) -> ()) {
guard let url = URL(string: "https://api.fastforex.io/fetch-all?from=USD&api_key=7ffe65c2ef-926f01d9e8-r7eql2") else { return }
URLSession.shared.dataTask(with: url) { data, responce, error in
if let error = error {
completion(.failure(error))
return
}
guard let safeData = data else { return }
do {
let currency = try JSONDecoder().decode(CurrencyModel.self, from: safeData)
completion(.success(currency))
}
catch {
completion(.failure(error))
}
}
.resume()
}
func fetchNewData(completion: @escaping (Result<CurrencyNewModel,Error>) -> ()) {
guard let url = URL(string: "https://api.fastforex.io/currencies?api_key=7ffe65c2ef-926f01d9e8-r7eql2") else { return }
URLSession.shared.dataTask(with: url) { data, responce, error in
if let error = error {
completion(.failure(error))
return
}
guard let safeData = data else { return }
do {
let currency = try JSONDecoder().decode(CurrencyNewModel.self, from: safeData)
completion(.success(currency))
}
catch {
completion(.failure(error))
}
}
.resume()
}
}
P.S. If you want to see the API, check the links in fetchData and fetchNewData, It's a free trial, so doesn't matter
CodePudding user response:
Your error says:
Value of type '[Currency]' has no member 'fullName'
So it seems that api.currencies
is an array – the array itself has no member fullName
, only one single element of it has.
try this:
ForEach(api.currencies, id:\.self) { currency in
Text(currency.fullName)
}