I have project, where two list of different banks show currency rate. And I want when I choose currency in first List, second List will have autoscrolling to the same currency. I saw tutorials with buttons, but it's not what I need. I thought use onTapGesture, but I can't realise how to involve it in right way. ExchangeRatesPB(ccy) and ExchangeRatesNBU(cc) have the same short name of some currencies: "USD", "EUR", "RUR". Thanks for help anyway.
struct ContentView: View {
@State private var date = Date()
@State var currenciesPB: [ExchangeRatesPB] = []
@State var currenciesNBU: [ExchangeRatesNBU] = []
@State var scrollToCurrency: String = ""
var body: some View {
ZStack {
Color(.systemGray6)
.edgesIgnoringSafeArea(.all)
VStack {
HStack {
Spacer(minLength: 110)
Text("Exchange rates")
.font(.title2)
.padding()
Spacer()
Image(systemName: "chart.bar.xaxis")
.font(.title)
.padding()
}
.foregroundColor(.white)
.padding(.top)
.background(Color.init(#colorLiteral(red: 0.4558259845, green: 0.5886077285, blue: 0.5515387654, alpha: 1)))
.edgesIgnoringSafeArea(.top)
//PB
VStack {
HStack {
Text("PrivatBank")
.foregroundColor(Color.init(#colorLiteral(red: 0.3549223542, green: 0.3776315749, blue: 0.4196012616, alpha: 1)))
Spacer(minLength: 100)
Image(systemName: "calendar")
.foregroundColor(.gray)
DatePicker("", selection: $date, displayedComponents: .date)
}
.font(.title2)
.padding(10)
HStack(spacing: 60) {
Text("Currency")
Text("Purchase")
Text("Sale")
} .foregroundColor(.gray)
VStack {
// ScrollView {
List(currenciesPB, id: \.self) { currencyPB in
VStack {
HStack(spacing: 60) {
Text(currencyPB.ccy)
.id(currencyPB.ccy)
Text(currencyPB.sale)
Text(currencyPB.buy)
}
// .onTapGesture {
//scrollToCurrency = currencyPB.ccy
//print(scrollToCurrency)
// }
.foregroundColor(Color.init(#colorLiteral(red: 0.3549223542, green: 0.3776315749, blue: 0.4196012616, alpha: 1)))
}
}
// }
.padding(.top)
.onAppear() {
ApiPB().getCurrency { (currenciesPB) in
self.currenciesPB = currenciesPB
}
}
}
}
//NBU
VStack {
HStack {
Text("NBU")
.foregroundColor(Color.init(#colorLiteral(red: 0.3549223542, green: 0.3776315749, blue: 0.4196012616, alpha: 1)))
Spacer(minLength: 150)
Image(systemName: "calendar")
.foregroundColor(.gray)
DatePicker("", selection: $date, displayedComponents: .date)
}
.font(.title2)
.padding(10)
// ScrollView {
ScrollViewReader { value in
VStack {
List(currenciesNBU, id: \.self) { currencyNBU in
VStack {
HStack(spacing: 50) {
Text(currencyNBU.txt)
Spacer()
VStack {
HStack {
Text(String(currencyNBU.rate))
Text("UAH")
}
}
}
.listRowBackground(Color(.systemGray6))
.foregroundColor(Color.init(#colorLiteral(red: 0.3549223542, green: 0.3776315749, blue: 0.4196012616, alpha: 1)))
}
}
.onChange(of: scrollToCurrency) { _ in
value.scrollTo(scrollToCurrency, anchor: .top)
}
.padding(.top)
.onAppear() {
ApiNBU().getCurrency { (currenciesNBU) in
self.currenciesNBU = currenciesNBU
}
}
}
}
// }
}
}
}
}
}
struct ExchangeRatesPB: Codable, Hashable {
let ccy: String
let base_ccy: String
var buy: String
var sale: String
}
class ApiPB {
func getCurrency(completion: @escaping ([ExchangeRatesPB]) -> ()) {
guard let url = URL(string: "https://api.privatbank.ua/p24api/pubinfo?json&exchange&coursid=5") else { return }
URLSession.shared.dataTask(with: url) { (data, _, _) in
let currenciesPB = try! JSONDecoder().decode([ExchangeRatesPB].self, from: data!)
DispatchQueue.main.sync {
completion(currenciesPB)
}
}
.resume()
}
}
struct ExchangeRatesNBU: Codable, Hashable {
let r030: Int
let txt: String
var rate: Double
var cc: String
}
class ApiNBU {
func getCurrency(completion: @escaping ([ExchangeRatesNBU]) -> ()) {
guard let url = URL(string: "https://bank.gov.ua/NBUStatService/v1/statdirectory/exchange?date=20200302&json") else { return }
URLSession.shared.dataTask(with: url) { (data, _, _) in
let currenciesNBU = try! JSONDecoder().decode([ExchangeRatesNBU].self, from: data!)
DispatchQueue.main.sync {
completion(currenciesNBU)
}
}
.resume()
}
}
Your approach is totally fine, you missed just once thing. First argument in scrollTo()
is id
, and when you're creating your list you've specified self
as id
. So to scroll to that element you need to pass the whole object you wanna scroll to, or just change id
for your list like this:
List(currenciesNBU, id: \.cc)