From c1feedd61c13952bf194228b985095feec115846 Mon Sep 17 00:00:00 2001 From: Nicholas Entin Date: Mon, 7 Aug 2023 22:37:59 -0700 Subject: [PATCH] Modernize SwitchControlViewController --- .../SwitchControlViewController.swift | 215 ++++++++++-------- 1 file changed, 119 insertions(+), 96 deletions(-) diff --git a/Example/AccessibilitySnapshot/SwitchControlViewController.swift b/Example/AccessibilitySnapshot/SwitchControlViewController.swift index 10e90df2..14fdc333 100644 --- a/Example/AccessibilitySnapshot/SwitchControlViewController.swift +++ b/Example/AccessibilitySnapshot/SwitchControlViewController.swift @@ -19,112 +19,135 @@ import UIKit final class SwitchControlViewController: AccessibilityViewController { - // MARK: - Private Properties + // MARK: - UIViewController - private let switchControls: [UISwitch] = (0..<8).map { _ in UISwitch() } + override func loadView() { + view = View() + } - /// UIView with the switch button trait that acts like a switch, but is not a UISwitch. - private let fakeSwitchView: UIView = .init() +} - /// UIView with the button and switch button traits that acts like a switch, but is not a UISwitch. - private let fakeSwitchButton: UIView = .init() +// MARK: - + +private extension SwitchControlViewController { + + final class View: UIView { + + // MARK: - Life Cycle + + override init(frame: CGRect) { + super.init(frame: frame) + + switchControls[0].isOn = true + + switchControls[1].isOn = false + + switchControls[2].isOn = true + switchControls[2].accessibilityLabel = "Label" + + switchControls[3].isOn = false + switchControls[3].accessibilityLabel = "Label" + + switchControls[4].isOn = true + switchControls[4].accessibilityLabel = "Label" + switchControls[4].accessibilityValue = "Value" + + switchControls[5].isOn = true + switchControls[5].accessibilityLabel = "Label" + switchControls[5].accessibilityValue = "Value" + switchControls[5].accessibilityHint = "Hint" + + switchControls[6].isOn = false + switchControls[6].accessibilityLabel = "Label" + switchControls[6].accessibilityValue = "Value" + switchControls[6].accessibilityHint = "Hint" + switchControls[6].accessibilityTraits.insert([ + .selected, + .button, + .header, + .link, + .adjustable, + .image, + .searchField, + ]) + + switchControls[7].isOn = false + switchControls[7].accessibilityLabel = "Label" + switchControls[7].accessibilityValue = "Value" + switchControls[7].accessibilityHint = "Hint" + switchControls[7].accessibilityTraits.insert([ + .selected, + .notEnabled, + .button, + .header, + .link, + .adjustable, + .image, + .searchField, + ]) + + switchControls.forEach { addSubview($0) } + + // Add a fake switch that has the switch button trait only, but is not a UISwitch. + fakeSwitchView.isAccessibilityElement = true + fakeSwitchView.accessibilityLabel = "Fake Label" + fakeSwitchView.accessibilityValue = "Value" + fakeSwitchView.accessibilityTraits.insert(UIAccessibilityTraits(rawValue: 0x0020000000000000)) + fakeSwitchView.frame.size = .init(width: 48, height: 32) + fakeSwitchView.backgroundColor = .lightGray + fakeSwitchView.layer.cornerRadius = 16 + addSubview(fakeSwitchView) + + // Add a fake switch that has the switch button and button traits, but is not a UISwitch. + fakeSwitchButton.isAccessibilityElement = true + fakeSwitchButton.accessibilityLabel = "Fake Label" + fakeSwitchButton.accessibilityValue = "Value" + fakeSwitchButton.accessibilityTraits.insert(.button) + fakeSwitchButton.accessibilityTraits.insert(UIAccessibilityTraits(rawValue: 0x0020000000000000)) + fakeSwitchButton.frame.size = .init(width: 48, height: 32) + fakeSwitchButton.backgroundColor = .lightGray + fakeSwitchButton.layer.cornerRadius = 16 + addSubview(fakeSwitchButton) + } - // MARK: - UIViewController + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } - override func viewDidLoad() { - super.viewDidLoad() - - switchControls[0].isOn = true - - switchControls[1].isOn = false - - switchControls[2].isOn = true - switchControls[2].accessibilityLabel = "Label" - - switchControls[3].isOn = false - switchControls[3].accessibilityLabel = "Label" - - switchControls[4].isOn = true - switchControls[4].accessibilityLabel = "Label" - switchControls[4].accessibilityValue = "Value" - - switchControls[5].isOn = true - switchControls[5].accessibilityLabel = "Label" - switchControls[5].accessibilityValue = "Value" - switchControls[5].accessibilityHint = "Hint" - - switchControls[6].isOn = false - switchControls[6].accessibilityLabel = "Label" - switchControls[6].accessibilityValue = "Value" - switchControls[6].accessibilityHint = "Hint" - switchControls[6].accessibilityTraits.insert([ - .selected, - .button, - .header, - .link, - .adjustable, - .image, - .searchField, - ]) - - switchControls[7].isOn = false - switchControls[7].accessibilityLabel = "Label" - switchControls[7].accessibilityValue = "Value" - switchControls[7].accessibilityHint = "Hint" - switchControls[7].accessibilityTraits.insert([ - .selected, - .notEnabled, - .button, - .header, - .link, - .adjustable, - .image, - .searchField, - ]) - - switchControls.forEach { view.addSubview($0) } - - // Add a fake switch that has the switch button trait only, but is not a UISwitch. - fakeSwitchView.isAccessibilityElement = true - fakeSwitchView.accessibilityLabel = "Fake Label" - fakeSwitchView.accessibilityValue = "Value" - fakeSwitchView.accessibilityTraits.insert(UIAccessibilityTraits(rawValue: 0x0020000000000000)) - fakeSwitchView.frame.size = .init(width: 48, height: 32) - fakeSwitchView.backgroundColor = .lightGray - fakeSwitchView.layer.cornerRadius = 16 - view.addSubview(fakeSwitchView) - - // Add a fake switch that has the switch button and button traits, but is not a UISwitch. - fakeSwitchButton.isAccessibilityElement = true - fakeSwitchButton.accessibilityLabel = "Fake Label" - fakeSwitchButton.accessibilityValue = "Value" - fakeSwitchButton.accessibilityTraits.insert(.button) - fakeSwitchButton.accessibilityTraits.insert(UIAccessibilityTraits(rawValue: 0x0020000000000000)) - fakeSwitchButton.frame.size = .init(width: 48, height: 32) - fakeSwitchButton.backgroundColor = .lightGray - fakeSwitchButton.layer.cornerRadius = 16 - view.addSubview(fakeSwitchButton) - } + // MARK: - Private Properties + + private let switchControls: [UISwitch] = (0..<8).map { _ in UISwitch() } + + /// UIView with the switch button trait that acts like a switch, but is not a UISwitch. + private let fakeSwitchView: UIView = .init() - override func viewDidLayoutSubviews() { - super.viewDidLayoutSubviews() + /// UIView with the button and switch button traits that acts like a switch, but is not a UISwitch. + private let fakeSwitchButton: UIView = .init() - switchControls.forEach { $0.sizeToFit() } + // MARK: - UIView - let statusBarHeight = UIApplication.shared.statusBarFrame.height + override func layoutSubviews() { + switchControls.forEach { $0.sizeToFit() } - var distributionSpecifiers: [ViewDistributionSpecifying] = [ statusBarHeight.fixed, 1.flexible ] - for subview in switchControls { - distributionSpecifiers.append(subview) - distributionSpecifiers.append(1.flexible) + let statusBarHeight = window?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0 + + var distributionSpecifiers: [ViewDistributionSpecifying] = [ statusBarHeight.fixed, 1.flexible ] + for subview in switchControls { + distributionSpecifiers.append(subview) + distributionSpecifiers.append(1.flexible) + } + distributionSpecifiers.append( + contentsOf: [ + fakeSwitchView.distributionItem, + 1.flexible, + fakeSwitchButton.distributionItem, + 1.flexible, + ] + ) + applySubviewDistribution(distributionSpecifiers) } - distributionSpecifiers.append(contentsOf: [ - fakeSwitchView.distributionItem, - 1.flexible, - fakeSwitchButton.distributionItem, - 1.flexible, - ]) - view.applySubviewDistribution(distributionSpecifiers) + } }