1

I have the following SwiftUI ButtonStyle:

public struct PrimaryButton: ButtonStyle {
    private let type: ButtonType
    @Environment(\.isEnabled) private var isEnabled

    public init() {
    }

    public func makeBody(configuration: Configuration) -> some View {
        configuration
            .label
            .font(.callout)
            .foregroundColor(textColor)
            .padding(padding)
            .background(backgroundColor)
            .clipShape(RoundedRectangle(cornerRadius: 4,
                                        style: .continuous))
            .opacity(configuration.isPressed ? 0.5 : 1)
    }

    private var padding: EdgeInsets {
            return EdgeInsets(top: 16,
                              leading: 16,
                              bottom: 16,
                              trailing: 16)
    }

    private var backgroundColor: Color {
        isEnabled ? .blue : .gray
    }

    private var textColor: Color {
        isEnabled ? Color.white : .gray
    }
}

And the following Preview code:

struct ButtonStyle_Previews: PreviewProvider {
    static var previews: some View {
        VStack {
            SwiftUI.Button(action:{}, label: {
                Text(verbatim: "Primary")
            }).buttonStyle(PrimaryButton())

            SwiftUI.Button(action:{}, label: {
                Text(verbatim: "PrimaryDisabled")
            }).buttonStyle(PrimaryButton())
            .disabled(true)
        }
        .padding()
    }
}

Surprisingly, I'm getting completely different results when trying to preview the same code in different iOS versions: enter image description here enter image description here

iOS 14.4, Xcode 12.2 - incorrect

enter image description here

iOS 14.5, Xcode 12.5.1 - correct

enter image description here

Note, that in both cases the button doesn't react to changes when disabled. On iOS 14.4 it looks like it's enabled, but it's not possible to press it.

It seems that the @Environment(\.isEnabled) value is ignored and simply defaulted to true. I had a similar issue with @Environment(\.horizontalSizeClass) where it behaved as if it was nil, being not .regular and not .compact. With iOS 14.5 this bug is fixed, but how can it be "backported" to the iOS 14.4?

  1. What's the reason for such an inconsistent behavior between iOS 14.4 and iOS 14.5?
  2. Are there any reasons in my code that could be causing it?
  3. Any solutions on iOS 14.4?
  4. If it's a SwiftUI bug, is it possible to rewrite the code of the PrimaryButton in some way that the button still could reflect changes in it's state (enabled/disabled).
Richard Topchii
  • 7,075
  • 8
  • 48
  • 115
  • 3
    You need a view to use it on older systems (environment passed only via views - view modifier is not a view), here was a demo https://stackoverflow.com/a/64255870/12299030. – Asperi Sep 07 '21 at 14:27
  • Interesting, that has almost resolved my issue. How about the text color? Is it possible to change? – Richard Topchii Sep 07 '21 at 14:52

0 Answers0