I am currently investigating an animation issue on iOS17 and discovered some behaviour different compared to iOS16 that I'm trying to understand. I've debugged this down to the fact that iOS17 behaves differently when certain modifiers are applied to a Text, such as .opacity or .blur, and then a text change is animated.
Text without .opacity
@State var text = "Start"
var body: some View {
Text(text)
.animation(.linear(duration: 1.0), value: text)
.background(Color.red)
.onAppear {
text = "Text after animation"
}
}
Result
The result:
Text with .opacity
Now consider the same code, but with an opacity modifier applied:
@State var text = "Start"
var body: some View {
Text(text)
.opacity(0.5)
.animation(.linear(duration: 1.0), value: text)
.background(Color.red)
.onAppear {
text = "Text after animation"
}
}
Result
The result on iOS16 is the same as above. On iOS17, however, this is the result:

So I have two basic questions:
- Is this some change on Apples side I missed? Can someone explain why this behaves differently?
- In my opinion, the new result of iOS17 is undesired – if I have text changes I usually want to cross-fade the text without it moving. I have a production app where this causes tiny movements of text that just look not clean. How can I get the iOS16 animation back on iOS17?

As a workaround, you can force a change of id every time the view is repainted:
I suppose, what this gives you is a transition from the old view to the new view, rather than an animated change to an existing view.