0

Consider the following.

fileprivate extension UIButton {
    override open var isSelected: Bool {
        didSet {
            self.titleLabel?.font = isSelected ? UIFont(name: "HelveticaNeue-Medium", size: 14) : UIFont(name: "HelveticaNeue-Light", size: 14)
        }
    }
}

After a while, a warning appears in xcode that asks me to change "open" to fileprivate. Of course if I do that, then I'm not overriding the same isSelected variable from UIButton and I get an error.

Is this an XCode bug? I cannot make the extension public or internal as the behaviour will alter all UIButtons in the app. Any ideas?

Update:

The exact warning is this. enter image description here

L_Sonic
  • 594
  • 6
  • 22
  • What was the exact warning you got? – TheAmateurProgrammer Jan 18 '17 at 16:04
  • The declaration is perfectly valid and it works as intended. The warning is wrong. – L_Sonic Jan 18 '17 at 16:14
  • The warning message is wrong due to a bug in the compiler's message file, it should be "Declaring OPEN var in a fileprivate extension", see http://stackoverflow.com/questions/40983010/cannot-override-open-method-declared-in-class-extension-in-another-module-swift for a similar issue. As a solution, you can remove `fileprivate` from the `extension`. – Martin R Jan 18 '17 at 16:21

1 Answers1

3

The funny thing is that Swift actually lets you do this. I believe it is intentional that you can not override public methods in private (fileprivate) context.

It is ambiguous to what you really want:

In your case you override the method in context which only scopes to the file itself. One might think that the override will only apply for the buttons inside this file but that is not true. Now every button in your application will actually have overridden method (have tested it). So your solution is definitely to have this method override inside a publicly exposed extension.

Note: I know it is a property and not a method but behind the scenes this is a method that is triggered after a setter on the object is called.

Matic Oblak
  • 16,318
  • 3
  • 24
  • 43
  • My mind is blown. It is indeed available everywhere! Then why the heck does fileprivate extensions exist then? – L_Sonic Jan 18 '17 at 16:30
  • 1
    @L_Sonic Not for overriding. It is for subclassing or for creating fileprivate classes. Not even for public protocol implementations. Use a subclass in your case. Also let me share an advice with you you will rarely see: When it comes to making extensions on the classes that are not yours (such as UIButton), avoid at all cost! Seriously, never ever do this unless there is really no other way to produce your solution. – Matic Oblak Jan 18 '17 at 16:33
  • Seemed cleaner than subclassing a whole class just to change a font. Thanks for the advice! – L_Sonic Jan 18 '17 at 16:37
  • 1
    @L_Sonic I feel you on that but unfortunately these things do not work that way. But if they did simply ask yourself one thing: When would the extension then actually work? If the button was created in this file? If a setter was called inside this file? If the button instance was used in this file? In general I practice to have a custom subclass of a button which is then used all over the app. You can then easily add other properties or logic. You can even add IB inspectables to control them in IB. – Matic Oblak Jan 18 '17 at 16:44