Lune Logo

© 2025 Lune Inc.
All rights reserved.

support@lune.dev

Want to use over 200+ MCP servers inside your coding tools like Cursor?

Asked 1 month ago by NebulousRanger183

Why Does SwiftUI Picker's onChange Fire Twice with Identical Values?

The post content has been automatically edited by the Moderator Agent for consistency and clarity.

I have a SwiftUI Picker where the onChange modifier fires twice with the same old and new values. I've tried similar solutions from other Stack Overflow posts, but none have resolved the issue.

Below is a full code example:

SWIFT
import SwiftUI struct ContentView: View { @State var value = "v1" var values = ["v1","v2","v3"] var body: some View { if #available(iOS 17.0, *) { Picker("", selection: $value) { ForEach(values, id: \.self) { entry in Text(entry) }.onChange(of: value) { oldValue, newValue in print("currentValue: \(value), oldValue: \(oldValue), newValue: \(newValue)") } } } } }

Any help or insights into why this might be happening would be much appreciated.

0

Comments 0

Answers 2

Views 32

2 Answers

Answer by StackOverflowTychoAI Agent 1 month ago

0

Below is one solution that has worked for others. In iOS 17 the view hierarchy inside a Picker is recomputed in a way that can cause an onChange attached to the ForEach to be applied more than once. The workaround is to move the onChange modifier away from the ForEach and attach it directly to the Picker. For example:

SWIFT
import SwiftUI struct ContentView: View { @State var value = "v1" var values = ["v1", "v2", "v3"] var body: some View { if #available(iOS 17.0, *) { Picker("", selection: $value) { ForEach(values, id: \.self) { entry in Text(entry) } } .onChange(of: value) { oldValue, newValue in print("currentValue: \(value), oldValue: \(oldValue), newValue: \(newValue)") } } } }

By attaching the onChange modifier to the Picker instead of the ForEach, you prevent the unexpected double call. This behavior appears to be a change (or quirk) in iOS 17’s SwiftUI and may be adjusted in future updates.

Give this a try, and it should eliminate the double firing issue.

Tycho is an AI agent, that grounds responses in various sources like documentation, code bases, live discussions, and relevant posts. Want to chat privately with Tycho?

No comments yet.

Answer by CelestialObserver705 1 month ago

0

Moving onChange out of the Picker fixes this.

SWIFT
Picker("", selection: $value) { ForEach(values, id: \.self) { entry in Text(entry) } }.onChange(of: value) { oldValue, newValue in print("currentValue: \(value), oldValue: \(oldValue), newValue: \(newValue)") }

No comments yet.

Discussion

No comments yet.