Exploring the onChange Modifier in SwiftUI

Inyene Etoedia
4 min readSep 25, 2023

--

In this article I will explain in simple terms how to use two swiftUI modifiers and when to use them.

Understanding OnChange Modifier

In SwiftUI, the onChange modifier is used to make our app respond to changes in things like the screen or data we’re using. It’s like setting up a “watcher” to see when something changes. This can work with various things we’re watching, even if they are a bit more complex, as long as we can easily compare their values.

The onChange modifier in SwiftUI is pretty easy to use. You tell it what you want to watch (like a string , integer or a boolean), and you also tell it what to do when that thing changes. That's it! It's like saying, "Hey, keep an eye on this, and when it changes, do this."

OnChange Syntax:
Before iOS 17 this is how onChange is written onChange(of:perform:)

.onChange(of: propertyToWatch) { newValue in
// Code to run when propertyToWatch changes to newValue
}

of: keyword is used to specify the property or state variable you want to observe for changes. It tells SwiftUI what to “keep an eye on.”

perform: keyword is followed by a closure (a block of code). This closure contains the actions you want to perform when the property you specified in of: changes. It's where you define what should happen in response to the change.

newValue: is the new value of the property when it changes.

What values can be Observed

Most of the time, it's used to watch data that's marked with @State, @StateObject, or @ObservableObject. However, there are special cases where you can use it to watch other data, even if it's not the main focus of the view.

For optional values, you only need to worry about the type inside the optional being watchable. It’s like saying, “I’m watching this data, and I’ll act when it changes, whether it’s the main data or not.”

Lets try an example here using a TextField. In this example want to watch the changes in the text entered by the user. Here's an example of how to use it:

import SwiftUI

struct ContentView: View {
@State private var text = ""

var body: some View {
TextField("Enter text", text: $text)
.onChange(of: text) { newValue in
print("Text changed to: \(newValue)")
}
}
}

In the example above :

We create a TextField where the user can input text, and we bind it to the @State property text.

We use the onChange(of:perform:) modifier with the text property as the property to watch for changes.

Inside the closure, we specify what should happen when the text property changes. In this case, we print the new value of the text to the console.

Whenever the user types something in the TextField, the onChange modifier will capture the change and execute the code in the closure.

Old value and New value:

Sometimes you might want to know both the old value and the new value of something you’re keeping an eye on. With this feature, you can easily get both of those values when the thing changes.

import SwiftUI

struct ContentView: View {
@State private var text = ""
@State private var previousText = ""
var body: some View {
VStack {
TextField("Enter text", text: $text)
.padding()
.border(Color.gray)

Text("Current Text: \(text)")
Text("Previous Text: \(previousText)")
}
.onChange(of: text) { newValue in
previousText = text
text = newValue
}
}
}

With this method, you can keep track of: and show both the text that’s currently in the TextField and the text that was there before. The onChange tool helps us notice when changes happen and make sure the right information is kept up to date.

limit text length:

The onChange modifier in SwiftUI can be used to limit the length of text entered in a TextField. This particular method can be handy when you want to restrict the user from entering more characters than allowed, for instance when your user is expected to enter their phone number, account number or password. Here's an example of how to use the onChange modifier to limit text length in a TextField:

import SwiftUI

struct ContentView: View {
@State private var text = ""
let characterLimit = 10 // Define the maximum character limit
var body: some View {
VStack {
TextField("Enter text", text: $text)
.padding()
.border(Color.gray)
}
.onChange(of: text) { newValue in
if newValue.count > characterLimit {
text = String(newValue.prefix(characterLimit))
}
}
}
}

In the example above, whenever the user enters text in the textfield, the onChange modifier will be triggered. The onChange modifier will then check the length of the text state variable. If the length of the text state variable is greater than 10, the onChange modifier will truncate the string to the first 10 characters.

Conclusion

n this article, we’ve explored how to use the onChange tool in SwiftUI. It's like having a watchful eye in your app, ready to react when things change, whether it's data or what the user does. It's simple to use; you just tell it what to watch and what to do when things change.

We’ve also shown real examples, like watching text changes or limiting how much text you can enter. These examples make your app more user-friendly and give you control.

Coming up next, we’ll dive into the onReceive tool, which is like having a secret messenger for your data.

--

--