/swift

UIView.Visibility extension

Here's a UIView extension I like to add to my Swift projects. It's a more verbose way of declaring UIView's isHidden property:

import UIKit

extension UIView {
    public enum Visibility {
        case visible, hidden

        var isHidden: Bool {
            switch self {
            case .visible: return false
            case .hidden: return true
            }
        }
    }
}

Those who've worked with me for some time may have heard me say something to the tune of "Enums are the solution to everything", and this may be the ultimate expression of it.

But why would one replace a perfectly succinct data type like Boolean by a 2-case enumeration? Isn't it overkill?

It might be. But in my mind, isHidden is counterintuitive. It's much easier for me to reason about a view's Visibility, than whether it's hidden or not. I have many a time scratched my head, wondering about why a view isn't showing, just to realize I set isHidden to the exact opposite of what I intended. Not so with Visibility!

Here's an example

let profileControllerVisibility: Observable<UIView.Visibility> = 
  environment
    .session
    .activeUser
    .map { $0 == nil ? .hidden : .visible }

profileControllerVisibility
  .map { $0.isHidden }
  .bind(to: profileController.view.rx.isHidden)
  .disposed(by: disposeBag)

The above snippet inspects the active user on the current session, decides on whether the profile controller component should be visible or not, and uses an RxCocoa binding to reactively pass this state on to the isHidden property.

Is it better than just setting isHidden to true when $0 == nil? I couldn't say objectively, but I just like the extra verbose expression of intent in this case.

Other applications for 2-case enums

This pattern can be applied to any number of boolean conditions where you want to express more than just the on or off"ness" of something. And since you're creating a whole new type, you're giving yourself the opportunity to easily extend it in the future with domain-specific functionality, that is easily tested and simple to reason about.


Can you think of more cases where this pattern can be applied to enhance the readability of your code?

Tagged with: