Skip to content

Instantly share code, notes, and snippets.

@kevin-hirsch
Last active October 23, 2020 09:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kevin-hirsch/3f8acc7470509205b1f68fee2ac8512d to your computer and use it in GitHub Desktop.
Save kevin-hirsch/3f8acc7470509205b1f68fee2ac8512d to your computer and use it in GitHub Desktop.
VoiceOver vs. symbols and units
extension NSObject {
// The same can be done for `accessibilityValue` and `accessibilityHint` if needed.
var smartAccessibilityLabel: String? {
get { accessibilityLabel }
set {
setInBackgroundIfAccessibilityOff(
\.accessibilityLabel,
to: newValue?.improvedForReadability
)
}
}
private func setInBackgroundIfAccessibilityOff(
_ keyPath: ReferenceWritableKeyPath<NSObject, String?>,
to value: @autoclosure @escaping () -> String?
) {
if UIAccessibility.isVoiceOverRunning
|| UIAccessibility.isSpeakScreenEnabled
|| UIAccessibility.isSwitchControlRunning
{
self[keyPath: keyPath] = value()
} else {
DispatchQueue.global(qos: .background).async { [weak self] in
let generatedValue = value() // In case it takes time, it's done in background
DispatchQueue.main.async {
// Since it's about UI, we do this on the main thread, just to be sure ;)
self?[keyPath: keyPath] = generatedValue
}
}
}
}
}
private let number = #"\d(?:[\.,:\s]?\d)*"#
extension String {
var improvedForReadability: String {
// List all of the substitutions we want to make
// Array of tuples of (pattern to match, what to replace it with)
let substitutions = [
("/", " per "),
("(CO²|CO₂)", "CO2"),
("kWh", "Kilowatt hour"),
("(n|N)°", "number"),
("(\(number)) ?/ ?(\(number))", "$1 of $2"),
("(+/-|+-|±)", "more or less")
]
return substitutions.reduce(self) { (string, substitution) in
let (pattern, replacement) = substitution
return string.replacing(pattern: pattern, with: replacement)
}
}
func replacing(pattern: String, with replacement: String, options: NSRegularExpression.Options = []) -> String {
let regex = try! NSRegularExpression(pattern: pattern, options: options)
return regex.stringByReplacingMatches(
in: self,
options: [],
range: NSRange(location: 0, length: count),
withTemplate: replacement
)
}
}
@kevin-hirsch
Copy link
Author

kevin-hirsch commented Oct 22, 2020

Can be used like:

label.smartAccessibilityLabel = "2 - 3 bd. • 76 m²" // => "from 2 to 3 bedrooms, 76 square meters"

or:

label.accessibilityLabel = "2 - 3 bd. • 76 m²".improvedForReadability // same result as previous

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment