Thanks, @anils, that got me part of the way there. When I run your solution on both macOS and iOS (not in the simulator, but actually running it on my devices in both cases), the TextField shows “GBP 0.00” on launch. If I delete the contents of the TextField and type “100” it resolves to “GBP 100.00”. So far so good. When I change the currency in the CurrencyPicker to e.g. NZD the TextField changes to display “NZD 100.00”. Fantastic – at this point I thought the issue had been solved. But then if I type anything else in the TextField, e.g. if I delete what's there and type “200”, the formatting reverts to GBP e.g. “GBP 200.00” (although the underlying value for currency and amount.currency and the value displayed in the Picker will all remain .NZD).
Funnily enough, although I initially thought this was at least some progress, when I went back to my original code I realised that my original code did the same thing (i.e. the formatting would initially update when the Picker value was first changed, but would revert as soon as something else is typed in the TextField).
Interestingly, I did notice a slight difference between macOS and iOS. In your solution, the CurrencyAmount View takes a binding to an Amount struct which has value and currency properties. It also has a separate @State variable for currency which it passes to the CurrencyPicker instead of $amount.currency. And then it uses the .onChange modifier to keep currency and amount.currency in sync.
On macOS, I can simplify your solution, delete the @State variable for currency, and just pass $amount.currency to the Currency Picker and get the exact same effect (example code below). But on iOS, the below code results in the Picker continuing to display the initial selection even when the underlying value is changed. So your additional step seems necessary on iOS but not on macOS.
For what it's worth, here's my code that had the same effect as @anils' suggestion on macOS but not on iOS.
import SwiftUI
struct Amount {
var value: Decimal
var currency: CurrencyCode
}
struct ContentView: View {
@State var amount = Amount(value: Decimal(), currency: .GBP)
var body: some View {
NewCurrencyAmount(title: "Some label", amount: $amount)
}
}
struct NewCurrencyAmount: View {
let title: String
let prompt: String = ""
@Binding var amount: Amount
var body: some View {
HStack {
Spacer(minLength: 80)
TextField(title, value: $amount.value, format: .currency(code: amount.currency.rawValue), prompt: Text(prompt))
NewCurrencyPicker(selected: $amount.currency)
Spacer(minLength: 80)
}
}
}
struct NewCurrencyPicker: View {
@Binding var selected: CurrencyCode
let label = "Currency"
var body: some View {
Picker(label, selection: $selected) {
ForEach(CurrencyCode.allCases) {
Text($0.rawValue)
.tag($0)
}
}
}
}
enum CurrencyCode: String, CaseIterable, Identifiable {
var id: String { self.rawValue }
case AUD, CAD, EUR, GBP, NZD, USD
}