Sign in with Apple button appearance in dark mode

I'm using iOS 13 beta 6 and for me ASAuthorizationAppleIDButton doesn't change appearance when I override Interface Style to dark. It's placed inside a view with System Background Color and completely disappears after interface style change.

Is this expected behaviour?

I know that button has .black and .white styles but changing them conditionally from the code looks cumbersom in comparison to system-defined colors which change automatically.

Replies

Same question here. Looks pretty odd that this control doesn't adapt automatically to dark/light mode

This still seems to be the case now in iOS 13.3. From what I can tell in the guidelines Apple doesn't expect you to change the background of your login screen for dark mode and would prefer you picked one color and one button style.

I've created a component that will do the trick with light/dark mode support on Sign in with Apple button. Here is the code:


import AuthenticationServices
import SnapKit
import UIKit

@available(iOS 13.0, *)
class SignInWithAppleButton: UIControl {
  var cornerRadius: CGFloat = 0.0 { didSet { updateRadius() } }
  private var target: Any?
  private var action: Selector?
  private var controlEvents: UIControl.Event = .touchUpInside
  private lazy var whiteButton = ASAuthorizationAppleIDButton(type: .signIn, style: .white)
  private lazy var blackButton = ASAuthorizationAppleIDButton(type: .signIn, style: .black)

  override init(frame: CGRect) {
    super.init(frame: frame)
    setupButton()
  }

  @available(*, unavailable)
  required init?(coder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }

  override func addTarget(_ target: Any?, action: Selector, for controlEvents: UIControl.Event) {
    self.target = target
    self.action = action
    self.controlEvents = controlEvents
  }

  override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    super.traitCollectionDidChange(previousTraitCollection)
    setupButton()
  }
}

// MARK: - Private Methods
@available(iOS 13.0, *)
private extension SignInWithAppleButton {
  func setupButton() {
    switch traitCollection.userInterfaceStyle {
    case .dark:
      subviews.forEach { $0.removeFromSuperview() }
      addSubview(whiteButton)
      whiteButton.snp.makeConstraints { $0.edges.equalToSuperview() }
      whiteButton.cornerRadius = cornerRadius
      action.map { whiteButton.addTarget(target, action: $0, for: controlEvents) }
    case _:
      subviews.forEach { $0.removeFromSuperview() }
      addSubview(blackButton)
      blackButton.snp.makeConstraints { $0.edges.equalToSuperview() }
      blackButton.cornerRadius = cornerRadius
      action.map { blackButton.addTarget(target, action: $0, for: controlEvents) }
    }
  }

  func updateRadius() {
    switch traitCollection.userInterfaceStyle {
    case .dark:
      whiteButton.cornerRadius = cornerRadius
    case _:
      blackButton.cornerRadius = cornerRadius
    }
  }
}


You can add a target for this button as you would usually do for the button.

signInWithAppleButton.addTarget(self, action: #selector(signInWithAppleButtonTapped), for: .touchUpInside)


This is a specific solution to my problem where I had to support only one type of Apple sign-in button. I could make it more versatile by adding options to modify the style and type of the button. You can modify it to fit your purpose.

This works for me:
Code Block Swift
import AuthenticationServices
struct SignInWithAppleButton: UIViewRepresentable {
  @Environment(\.colorScheme) var colorScheme
  func makeUIView(context: Context) -> ASAuthorizationAppleIDButton {
     
    let button = ASAuthorizationAppleIDButton(
      authorizationButtonType: .continue,
      authorizationButtonStyle: colorScheme == .dark ? .white : .black)
     
    return button
  }
   
  func updateUIView(_ uiView: ASAuthorizationAppleIDButton, context: Context) {
  }
}
struct SingInWithAppleButton_Previews: PreviewProvider {
  static var previews: some View {
    VStack {
      SignInWithAppleButton()
        .frame(width: 300, height: 40)
        .cornerRadius(5)
        .shadow(radius: 3, x: 2, y: 2)
       
       
      SignInWithAppleButton()
        .frame(width: 300, height: 40)
        .cornerRadius(5)
        .shadow(radius: 3, x: 2, y: 2)
        .environment(\.colorScheme, .dark)
    }
  }
}


Just simple:

Code Block
let button: ASAuthorizationAppleIDButton = ASAuthorizationAppleIDButton(
   authorizationButtonType: .default,
   authorizationButtonStyle: UITraitCollection.current.userInterfaceStyle == .dark ? .white : .black
)