rwapp/A11yUITests

Suggestion: prefer `responds(to: Selector)` to swizzling?

Closed this issue · 1 comments

Hi Rob,

Just a quick suggestion that will let you avoid swizzling by checking if the object responds to the key you are interrogating.

This extension will also perform the cast in a separate guard to give you a more helpful error to log.

extension NSObject {
    func optionalValue<T>(for key: String) -> T? {
        guard
            self.responds(to: Selector(key)),
            let value = self.value(forKey: key)
        else {
            print("Unable to get property \"\(type(of: self)).\(key)\". This is likely due to a change in Apple's private API. Please raise an issue https://github.com/rwapp/A11yUITests/issues")
            return nil
        }
        guard let castValue = value as? T else {
            print("Unable to cast property \"\(type(of: self)).\(key)\" from `\(type(of: value))` to `\(T.self)`. This is likely due to a change in Apple's private API. Please raise an issue https://github.com/rwapp/A11yUITests/issues")
            return nil
        }
        return castValue
    }
}

final class Subclass: NSObject {
    @objc let notATrait = "Hello, is it me you're looking for?"
}

let traits: UIAccessibilityTraits = Subclass().optionalValue(for: "notATrait") ?? []
rwapp commented

Thank you @nesevis, this is a great suggestion. Would you like to raise a PR, or should I go ahead and add your suggestion in?