Some classes canāt be subclassed since the init is marked as unavailable in objc, which canāt be overridden in Swift. Fortunately thereās a workaround so you can super.init() from your subclass.
Solution
The fix for this issue is to introduce a class into the inheritance hierarchy with an init. This init needs to meet three requirements:
- The new init canāt override the parent init. The init is marked unavailable in the parent class and that includes subclasses.
- The new init canāt have zero parameters. The parent init has zero parameters, so adding your own init with zero parameters would require āoverrideā, breaking requirement 1.
- The new init canāt call the parent init. That would cause the same problem with the class that currently exists with your subclass ā the problemās just been moved one class up.
Example
Suppose the following Swift class that tries to extend an Objective-C class from the CoreBluetooth framework, CBPeripheral:
class Peripheral: CBPeripheral {
override init() {
print("init")
}
}Code language: Swift (swift)
This class overrides the parent classās init, which has been marked unavailable, therefore presenting an error.
Cannot override āinitā which has been marked unavailable.
Apple's documentation for CBPeer also tells you to not do this:
You typically donāt create instances of either CBPeer or its concrete subclasses. Instead, the system creates them for you during the process of peer discovery.
CBPeer Overview ā Apple Documentation
Letās add a parent to the hierarchy. This parent is a new class we create,
class CBPeripheralInitable: CBPeripheral {
init(_: Void = ()) {}
}
class Peripheral: CBPeripheralInitable {
init() {
print("init")
}
}
Code language: Swift (swift)
Adding an āinitableā class to the hierarchy using init(_: Void = ()). This init doesn't override the NSObject init which takes no arguments, since there is one argument. This Void argument could be another type, but using Void prevents accidentally passing an argument. A default value for the argument of () alongside no parameter name means the call site stays the same: init().

Leave a Reply