Search code examples
iosswiftiphone

I can't use if statement in onchange


first of all I have two textfields and when one of them is focused and changed something this textfield that is changed has to convert a number to the other textfield so my code of the textfield look like this

@State var leftAmount = ""
@State var rightAmount = ""

@State var showInfoScreen = false
@State var showSelectCurrency = false

@FocusState var leftTyping
@FocusState var rightTyping

@State var leftCurrency: Currency = .silverPiece
@State var rightCurrency: Currency = .goldPiece

var body: some View {
    ZStack{
        Image("background")
            .resizable()
            .ignoresSafeArea()
        
        VStack{
            Image("prancingpony")
                .resizable()
                .scaledToFit()
                .frame(height: 200)
            
            Text("Curreny Exchange")
                .foregroundColor(.white)
                .font(.largeTitle)
                .kerning(2)
            
            HStack{
                VStack{
                    HStack{
                        Image(leftCurrency.image)
                            .resizable()
                            .scaledToFit()
                            .frame(height: 33)
                        
                        Text(leftCurrency.name)
                            .font(.headline)
                            .foregroundColor(.white)
                    }
                    .onTapGesture {
                        showSelectCurrency = true
                    }.sheet(isPresented: $showSelectCurrency){
                        SelectCurrency(showSelectCurrency: $showSelectCurrency, topCurrency: $leftCurrency, bottomCurrency: $rightCurrency)
                    }
                    
                    TextField("Amount", text: $leftAmount)
                        .textFieldStyle(.roundedBorder)
                        .focused($leftTyping)
                        .onChange(of: leftAmount) { newValue in
                            if leftTyping {
                                rightAmount = leftCurrency.convert(leftAmount, to: rightCurrency)
                            }
                        }
                }
                
                Image(systemName: "equal")
                    .foregroundColor(.white)
                    .font(.largeTitle)
                
                VStack{
                    HStack{
                        
                        Text(rightCurrency.name)
                            .font(.headline)
                            .foregroundColor(.white)
                        
                        Image(rightCurrency.image)
                            .resizable()
                            .scaledToFit()
                            .frame(height: 33)
                    }
                    .onTapGesture {
                        showSelectCurrency = true
                    }.sheet(isPresented: $showSelectCurrency){
                        SelectCurrency(showSelectCurrency: $showSelectCurrency, topCurrency: $leftCurrency, bottomCurrency: $rightCurrency)
                    }
                    
                    TextField("Amount", text: $rightAmount)
                        .textFieldStyle(.roundedBorder)
                        .multilineTextAlignment(.trailing)
                        .focused($rightTyping)
                        .onChange(of: rightAmount) { newValue in
                            
                                leftAmount = rightCurrency.convert(rightAmount, to: leftCurrency)
                            
                        }
                }
            }
            .padding()
            .background(.black.opacity(0.5))
            .clipShape(Capsule())
            
            Spacer()
            
            HStack {
                Spacer()
                
                Button {
                    showInfoScreen = true
                } label: {
                    Image(systemName: "info.circle.fill")
                        .foregroundColor(.white)
                        .font(.largeTitle)
                }

            }
            .padding()
            .sheet(isPresented: $showInfoScreen) {
                InfoView(showInfoScreen: $showInfoScreen)
            }
        }
    }
}

}

and this is my func

func convert(_ amountString: String, to currency: Currency) -> String {
    
    guard let doubleAmount = Double(amountString) else {
        return "" // eğer kullanıcı textfield'a numara yerine harf yazarsa boş string return yapıyor yani textfield boş kalıyor
    }
    
    let convertedAmount = (doubleAmount / self.rawValue) * currency.rawValue
    
    return String(format: "%.2f", convertedAmount)

when I don't put the if statement everything works fine about converting, but when I put the if statement on the onChange it does nothing, no converts and nothing. I think I have to use the newValue on somewhere but I'm not sure so if you guys can help me with this problem.

This is my first question so I'm sorry if I couldn't explainn the best way.

I want to use that if statement about if right textfield is focused it'll type there and leave the other textfield, but when I put the if statement there, nothing works.


Solution

  • You are using the version of .onChange with one parameter that has been replaced in iOS 17.0, so it is now deprecated. The documentation has a useful note:

    Be aware that the replacements have slightly different behvavior. This modifier’s closure captures values that represent the state before the change. The new modifiers capture values that correspond to the new state.

    So inside your closures, the values are from before the change, with the important exception of newValue. For example, in this case:

    .onChange(of: leftAmount) { newValue in
        if leftTyping {
            rightAmount = leftCurrency.convert(leftAmount, to: rightCurrency)
        }
    }
    

    the values for leftTyping, leftCurrency, leftAmount and rightCurrency are all from before the change.

    Ways to try and fix

    1. Use the new version of .onChange

    You might find that it works if you use the new version of .onchange that takes two parameters:

    .onChange(of: leftAmount) { _, newValue in
    

    2. Use newValue in the closure

    If the new version of .onchange is not an option (because you need to support older iOS versions) then try replacing leftAmount with newValue inside the closure:

    .onChange(of: leftAmount) { newValue in
        if leftTyping {
            rightAmount = leftCurrency.convert(newValue, to: rightCurrency)
        }
    }
    

    The other case needs updating similarly - try replacing rightValue with newValue inside the closure (and add an if condition too).

    3. Use newValue to supply more information

    If making the simple change to the closure doesn't fix it then you will need to consider using a different value for the .onChange, so that newValue gives you more information. For example, you could use an empty string to indicate that the field did not have focus. Something like:

    let leftAmountEntered = leftTyping ? leftAmount : ""
    TextField("Amount", text: $leftAmount)
        .textFieldStyle(.roundedBorder)
        .focused($leftTyping)
        .onChange(of: leftAmountEntered) { newValue in
            if !newValue.isEmpty {
                rightAmount = leftCurrency.convert(newValue, to: rightCurrency)
            }
        }