Reputation: 430
OK, so I understand delegates. I am perplexed (in a language design sense) that in some recent Swift work I have encountered delegates that can only be implemented with an "override" qualifier. Specifically "controlTextDidEndEditing" as NSTextFieldDelegate of a NSTextField UI element. (Yes, this is OS X dev work, not IOS).
When implementing this delegate Xcode insists on an override qualifier for the func. If it is a "delegate" function, then what code/functionality up the hierarchy am I overriding and should I care? Inserting super.controlTextDidEndEditing in the implementation simply led to an infinite loop. My comprehension (perhaps faulty/incomplete) of a delegate has been that it defines a signature that the implementation matches.
The context is test panel with an TextField and Label dropped into a ViewController, a trivial test exercise. The only scenario that I can arrive at is that somewhere in the hierarchy above the ViewController some other class is already implementing controlTextDidEndEditing, which leads to the override requirement as soon as I try to implement it, which implies that I am destroying some existing level of functionality. I did experiment with subclassing NSTextField with the same "override" required result.
Can anyone further my education by explaining the ins and outs of this ?
Thanks,
Alan.
Upvotes: 4
Views: 1124
Reputation: 25619
This is an example of an obsolete design pattern in older Objective-C code that doesn't map well to Swift. (It's more of a problem with the earliest AppKit code rather than UIKit. Expect Apple to continue to clean up these issues as time goes on.)
controlTextDidEndEditing isn't actually part of the NSTextFieldDelegate
protocol (or any other protocols). Instead, it's declared as an Objective-C "informal protocol":
@interface NSObject(NSControlSubclassNotifications)
- (void)controlTextDidBeginEditing:(NSNotification *)obj;
- (void)controlTextDidEndEditing:(NSNotification *)obj;
- (void)controlTextDidChange:(NSNotification *)obj;
@end
An informal protocol is like a class extension without an implementation, and their use dates back to a time when Objective-C didn't support formal protocols or optional protocol methods.
Swift doesn't have informal protocols. Instead, it appears as an extension to NSObject
.
extension NSObject {
func controlTextDidBeginEditing(obj: NSNotification)
func controlTextDidEndEditing(obj: NSNotification)
func controlTextDidChange(obj: NSNotification)
}
But Swift doesn't know that this is an informal protocol. As a result, Swift will let you call controlTextDidEndEditing()
on any NSObject
, even though NSObject does not implement that method.
Likewise, when you implement one of these methods in your own class, Swift will force you to use the override
keyword because it thinks you're overriding a method on NSObject
, even though that's not the case.
Upvotes: 4
Reputation: 5536
You don't override delegates, you override getters and setters. BUT, classes like UITableViewController conform to the delegate and the datasource, which means they already implement the methods. You override them because, yes, the superclass implements those already.
When you override delegate methods, I don't think you make a superclass call unless the superclass actually performs some function. NSTextField
's controlTextDidEndEditing
is probably implemented by NSTextField
itself as an empty implementation, which is why you need to override.
Upvotes: 0