4

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.

altimes
  • 380
  • 2
  • 13

2 Answers2

4

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.

Community
  • 1
  • 1
Darren
  • 25,520
  • 5
  • 61
  • 71
  • Ahhh, so the apple swift doco for NSControl that describes them as delegates is describing functional intent rather than implementation reality. Good answer, I am now comfortable that the override requirement is just, really what I think of as, syntactic noise. Swift, I will say, is vastly quieter in that area than Objective C. A language that I already enjoy coding in. – altimes Apr 12 '15 at 08:41
0

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.

Schemetrical
  • 5,506
  • 2
  • 26
  • 43
  • That agrees with my current comprehension of what is happening, but I am still puzzled as to why, as a designer, you would design a class to adopt a protocol and then implement an optional function within that protocol with a empty implementation forcing those using the class to override a protocol function. As a designer I would only implement the protocol methods of specific value to the class that I am creating. Hence the "I cannot see why it is this way" – altimes Apr 12 '15 at 07:28
  • This is a common pattern for classes that declare a protocol that they want their subclass to conform to. They conform to it themselves by having a default implementation (to prevent empty implementation and crashes), so your subclass automatically inherits from the implementation and can choose to override particular methods. An example is `UITableView`'s `-numberOfSectionsInTableView` that automatically returns 1 by default. Just a pattern, nothing special. – Schemetrical Apr 12 '15 at 08:55
  • Also, controlTextDidEndEditing isn't actually a protocol, I believe its a class method that you inherit and override, that gets called when text ends editing. – Schemetrical Apr 12 '15 at 08:56