How can I override readonly property of a Swift superclass, from a subclass, to make the property read-write?
I want to do that, because that is what the iOS UIResponder
documentation says is required. However, I'm getting an error when I try to implement what I think the Swift 5 documentation says can be done:
Swift 5 documentation
Inheritance
Overriding Property Getters and Setters:You can present an inherited read-only property as a read-write property by providing both a getter and a setter in your subclass property override.
What Went Wrong:
Based on aforementioned Swift docs statement, for which I found no accompanying example, I created the following subclass, at which XCode generates this error message:
"Cannot assign to property: 'inputAccessoryViewController' is a get-only property"
My Subclass:
class InputAccessoryEnabledTextView : UITextView {
override var inputAccessoryViewController: UIInputViewController? {
get { super.inputAccessoryViewController }
set { super.inputAccessoryViewController = newValue }
}
}
UIResponder
Declaration
var inputAccessoryViewController: UIInputViewController? { get }Discussion
This property is typically used to attach an accessory view controller to the system-supplied keyboard that is presented for UITextField and UITextView objects. The value of this read-only property is nil. If you want to attach custom controls to a system-supplied input view controller (such as the system keyboard) or to a custom input view (one you provide in the inputViewController property), redeclare this property as read-write in a UIResponder subclass. You can then use this property to manage a custom accessory view. When the receiver becomes the first responder, the responder infrastructure attaches the accessory view to the appropriate input view before displaying it.
Note: I do see a question from 6 years ago on Stack Overflow that got no accepted answers and doesn't seem to properly answer the question, so please don't flag this as a dup without a good reason. Perhaps these questions can be merged later
CodePudding user response:
super.inputAccessoryViewController
is not settable.
Your overridden implementation in the subclass, self.inputAccessoryViewController
is.
By adding a setter to the property in a subclass, you don't automatically also add the same thing in the superclass. What's in the subclass stays in the subclass.
So it's not that you can't override a property by adding a setter, you just can't set this here:
override var inputAccessoryViewController: UIInputViewController? {
get { super.inputAccessoryViewController }
set { super.inputAccessoryViewController = newValue }
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}
You can do other things, like:
override var inputAccessoryViewController: UIInputViewController? {
get { super.inputAccessoryViewController }
set { print("I just go set to \(newValue)") }
}
But that's not very useful. What you want is probably:
private var myInputAccessoryController: UIInputViewController?
override var inputAccessoryViewController: UIInputViewController? {
get { myInputAccessoryController }
set { myInputAccessoryController = newValue }
}