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()isid, and when you're creating your list you've specifiedselfasid. So to scroll to that element you need to pass the whole object you wanna scroll to, or just changeidfor your list like this: