I'm facing a problem with creating an variable. Here's an example what I've wanted to do:
I have JSON data in [ ]. I'm choosing smth in the picker and this changes pickerSelection1 and I can show in the view this string. Code is looking like this:
var cc1: String {
guard api.currencyCode1.count > 0 else {
return "err"
}
let cc1 = api.currencyCode1[pickerSelection1]
return cc1
}
Here's what I'm trying to do in the new project:
var cc1: String {
guard api.currencies.count > 0 else {
return "err"
}
ForEach(api.currencies, id: \.self) { cc1 in // BUG: Static method 'buildBlock' requires that 'String.SubSequence' (aka 'Substring') conform to 'AccessibilityRotorContent'
let cc1 = cc1.currencyCode[$pickerSelection1] // BUG: Subscript 'subscript(_:)' requires that 'Binding<Int>' conform to 'RangeExpression'
cc1
}
}
I'm pretty sure I'm doing smth wrong and I'm not supposed to use : String { }
. Need your advise, ladies and gentlemen.
P.S.: here's the whole code:
// Model
import Foundation
struct CurrencyModel: Codable {
var results: [String:Double]
}
struct CurrencyNewModel: Codable {
var currencies: [String:String]
}
struct Currency: Codable, Hashable {
let currencyCode: String
let fullName: String
var price: Double
}
// ViewModel
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()
}
}
// View
import SwiftUI
struct CurrencyView: View {
@StateObject var api = CurrencyViewModel()
@State var pickerSelection1 = 1
@State var pickerSelection2 = 1
var body: some View {
VStack {
Picker("", selection: $pickerSelection1) {
ForEach(api.currencies, id: \.self) { c1 in
Text(c1.currencyCode " " c1.fullName)
}
}
.id(UUID())
.labelsHidden()
Picker("", selection: $pickerSelection2) {
ForEach(api.currencies, id: \.self) { c2 in
Text(c2.currencyCode " " c2.fullName)
}
}
.id(UUID())
.labelsHidden()
}
}
var cc1: String {
guard api.currencies.count > 0 else {
return "err"
}
ForEach(api.currencies, id: \.self) { cc1 in
let cc1 = cc1.currencyCode[$pickerSelection1]
cc1
}
}
}
struct CurrencyView_Previews: PreviewProvider {
static var previews: some View {
CurrencyView()
}
}
CodePudding user response:
ForEach
is only for returning View
s
you should use
for cc1 in api.currencies{
//The rest of your code
}
and use pickerSelection1
without the $
The other issue may be that the pickerSelection1
type does not match c1
's type.
They should match or else the selection part of the operation will not work as you expect.