3

I saw this question, with this code:

protocol Flashable {}

extension Flashable where Self: UIView 
{
    func flash() {
        UIView.animate(withDuration: 0.3, delay: 0, options: .curveEaseIn, animations: {
            self.alpha = 1.0 //Object fades in
        }) { (animationComplete) in
            if animationComplete == true {
                UIView.animate(withDuration: 0.3, delay: 2.0, options: .curveEaseOut, animations: {
                    self.alpha = 0.0 //Object fades out
                    }, completion: nil)
            }
        }
    }
}

And I wonder why do we you not just directly just extend UIView? Or in similar cases extend UIViewController why twist it around with a where Self:

  • Is it so that we increase our intent and when other developers come they would see that hey this class is conforming to Flashable, Dimmable, etc?
  • Also our UIView would have separate meaningful extensions? Instead of different unNamed extensions to UIView or UIViewController?
  • Are there any specific Apple guidelines on this subject for POP? I've seen there developer doing it this way but not sure of the why...
Community
  • 1
  • 1
mfaani
  • 33,269
  • 19
  • 164
  • 293
  • 3
    Imagine the government was building a military building with a "self destruct" feature. Imagine they put this feature as an extension of `Building`. Now your home (a `Buiding`) inherits this "self destruct" feature. How would you feel about that? – Alexander Jan 17 '17 at 21:02

1 Answers1

7

This approach is preferable to using UIView directly, as in

extension UIView {
    func flash() {
        ...
    }
}

because it lets programmers decide which UIView subclasses they wish to make Flashable, as opposed to adding flash functionality "wholesale" to all UIViews:

// This class has flashing functionality
class MyViewWithFlashing : UIView, Flashable {
    ...
}
// This class does not have flashing functionality
class MyView : UIView {
    ...
}

Essentially, this is an "opt in" approach, while the alternative approach forces the functionality without a way to "opt out".

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • What's wrong with having it wholesale? And by opt out you mean what exactly? That I can't have a public func named flash() elsewhere because I extended UIView directly? – mfaani Jan 17 '17 at 20:57
  • 2
    @Honey The problem with wholesale addition is that flashing functionality would become available to views on which you never meant to call `flash()`, and the compiler would not be able to help you detect this situation. The extension becomes part of all `UIView` implementations, including ones that you have not coded yet. By "no opt out" I mean that, once `extension UIView` is in place, Swift does not offer you a syntax to say "I don't want this particular `UIView` to have flashing functionality". – Sergey Kalinichenko Jan 17 '17 at 21:04
  • 2
    Not at all. @dasblinkenlight means exactly what he said - flash() is available for every single UIView (and UIKit subview) that has this extension. Think in terms of this: If this UIView extension was part of a third party plug-in, or part of a large team-maintained app... where do you document things? Where do you provide an override function? Who would know? YES. You CAN extend this at the UIView level. But maybe you should do it elsewhere. –  Jan 17 '17 at 21:05
  • 1
    @dasblinkenlight It makes much more sense now. Basically saying: Don't leave it to the developer to decide whether or not to call `flash()`—when it's not needed at all. Let the compiler manage it for you. It's just better coding. – mfaani Jan 17 '17 at 21:14