0

Is it a bug of Swift 5.0.1 or Xcode?

This is in the playground with Xcode 10.2.1.

The codes are:

extension UIColor {
    @objc class var myGolden: UIColor {
        return self.init(red: 1.000, green: 0.894, blue: 0.541, alpha: 0.900)
    }
}
print(UIColor.myGolden)

class MyUIColor: UIColor {
    override class var myGolden: UIColor {
        return super.init(red: 1.000, green: 0.894, blue: 0.541, alpha: 0.750)
    }
}
print(MyUIColor.myGolden)

The playground does not indicate any error for the class MyUIColor

The output is:

UIExtendedSRGBColorSpace 1 0.894 0.541 0.9

libc++abi.dylib: terminating with uncaught exception of type NSException

and the runtime error says:

error: Execution was interrupted, reason: signal SIGABRT. The process has been left at the point where it was interrupted, use "thread return -x" to return to the state before expression evaluation.

rmaddy
  • 314,917
  • 42
  • 532
  • 579
user2158697
  • 107
  • 5
  • 2
    Full error message (that could be usefull) tested in iOS Simulator: "*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[iOSTest.MyUIColor initWithRed:green:blue:alpha:]: unrecognized selector sent to class 0x..." – Larme May 29 '19 at 12:36
  • 2
    Possible duplicate of [Overriding methods in Swift extensions](https://stackoverflow.com/questions/38213286/overriding-methods-in-swift-extensions) – holex May 29 '19 at 12:36
  • 3
    @holex: Unless I am mistaken, this is *not* the same issue. Here the property is overridden in a subclass, not in the extension. – Martin R May 29 '19 at 12:47
  • 1
    Even though my answer solve the runtime error, it's not really clear why your code doesn't work. Inside of a class function/computed property, `self` and `super` should refer to the type of the class/struct, so in your case `self.init` and `super.init` should be equivalent to `UIColor.init`. Moreover, trying out an equivalent code but using only pure Swift classes, it all works fine. I think you've probably found an error in the Swift/Objective-C bridging. – Marco May 29 '19 at 16:08

2 Answers2

1

Changing the self.init and super.init calls to UIColor.init fixes the issue. You should only call self.init and super.init from convenience initialisers or subclass initialisers respectively, when creating an instance of your class in a computed property or any other functions, you should be calling the init methods using the type name rather than self or super.

extension UIColor {
    @objc class var myGolden: UIColor {
        return UIColor(red: 1.000, green: 0.894, blue: 0.541, alpha: 0.9)
    }
}
print(UIColor.myGolden)

class MyUIColor: UIColor {
    override class var myGolden: UIColor {
        return UIColor(red: 1.000, green: 0.894, blue: 0.541, alpha: 0.75)
    }
}
print(MyUIColor.myGolden)
Dávid Pásztor
  • 51,403
  • 9
  • 85
  • 116
1

The problem isn't the class variable override, is instead the improper use of self.init and super.init. You should change the code as follows:

extension UIColor {
    @objc class var myGolden: UIColor {
        return UIColor(red: 1.000, green: 0.894, blue: 0.541, alpha: 0.900)
    }
}
print(UIColor.myGolden)

class MyUIColor: UIColor {
    override class var myGolden: UIColor {
        return UIColor(red: 1.000, green: 0.894, blue: 0.541, alpha: 0.750)
    }
}
print(MyUIColor.myGolden)
Marco
  • 1,572
  • 1
  • 10
  • 21