SwiftUI Stepper buttons unexpectedly disabled when using increment/decrement functions

Originator:mkflint
Number:rdar://FB7669491 Date Originated:19 April 2020
Status:Open Resolved:
Product:SwiftUI Product Version:Xcode 11.4
Classification:Bug Reproducible:Yes
 
Please describe the issue:
If a SwiftUI Stepper has increment/decrement functions _outside of the View_, then the +/-buttons can become disabled unexpectedly

Please list the steps you took to reproduce the issue:
1. Add the attached SwiftUI View to an iOS project
2. Run the app
3. Increment/decrement the first Stepper - note that it consistently works correctly
4. Increment/decrement the second stepper - note that the +/- buttons become disabled after a few clicks

The first stepper uses increment/decrement functions inside the View itself. The second uses functions inside a ViewModel (ie, not the View).

I don’t know why that would cause different behaviour, but I wouldn’t expect the +/- buttons to ever be disabled if the Stepper isn’t bound to a closed range.

What did you expect to happen?
+/- buttons should work, even if it’s using increment/decrement functions outside the View.

What actually happened?
+/- buttons can get disabled if the increment/decrement arguments reference a function outside of the View.



//
//  ContentView.swift
//  SwiftUI-stepper-problem
//

import SwiftUI

class ViewModel: ObservableObject {
    @Published var valueString: String = ""
    
    private var value: Int = 10 {
        didSet {
            self.updateUI()
        }
    }
    
    init() {
        self.updateUI()
    }
    
    private func updateUI() {
        self.valueString = "value: \(self.value)"
    }
    
    func increment() {
        self.value += 1
    }
    
    func decrement() {
        self.value -= 1
    }
}

struct ContentView: View {
    @ObservedObject var viewModel = ViewModel()
    
    var body: some View {
        Form {
            // This first Stepper uses the `increment` and `decrement` functions in the View
            Section(header: Text("Increment/decrement functions in the view. This works well")) {
                Stepper(onIncrement: self.increment,
                        onDecrement: self.decrement) {
                            Text(self.viewModel.valueString)
                }
            }
            
            // This Stepper uses `increment` and `decrement` functions in the ViewModel directly. After a few clicks, the `-` or `+` button is disabled
            Section(header: Text("Increment/decrement functions in the viewmodel. This gets stuck")) {
                Stepper(onIncrement: self.viewModel.increment,
                        onDecrement: self.viewModel.decrement) {
                            Text(self.viewModel.valueString)
                }
            }
        }
    }
    
    func increment() {
        self.viewModel.increment()
    }
    
    func decrement() {
        self.viewModel.decrement()
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

Comments


Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!