The declaration of NSTextFieldDelegate really confuse me a lot.
In Xcode, I click "jump to defination" of NSTextFieldDelegate, and found:
#protocol NSTextFieldDelegate <NSControlTextEditingDelegate> #end
I have known that if we add a <...> syntax after a NSObject type (such as "id") declaration, that means this object comforms to the protocol specified in "<>".
However, books of Obj-C I have do not mentioned what it means when the "<>" means when it follows a protocol declaration...
So, Question 1: What does "<>" means when it is after a declaration of protocol?
I continued look into the NSControlTextEditingDelegate, and found several methods begin with "control:...". But what attracted me most was the text above the NSControlTextEditingDelegate defination:
#interface NSObject(NSControlSubclassNotifications)
- (void)controlTextDidBeginEditing:(NSNotification *)obj;
- (void)controlTextDidEndEditing:(NSNotification *)obj;
- (void)controlTextDidChange:(NSNotification *)obj;
#end
Oh, here comes new questions:
Question 2: What is the syntex "NSObject(NSControlSubclassNotifications)" means? What is NSControlSubclassNotifications actually?
Quesiont 3: What are the relationships among NSObject, NSControlSubclassNotifications and NSControlTextEditingDelegate? The apple doc simply says: "The NSTextFieldDelegate protocol adopts the NSControlTextEditingDelegate protocol and currently does not extend it further." But I could not understand its meaning...
It means that the protocol conforms to ("adopts") another protocol, so basically the protocol contains all the methods in both protocols. It's somewhat similar to subclassing.
It's a category, in this case used as an informal protocol. It fulfills pretty much the same purpose as a (formal) protocol here (though that's just one use case of categories), you'll mostly see this style in older APIs.
NSControlSubclassNotification is a category on NSObject. It basically adds new methods to all classes that inherit from NSObject. NSTextFieldDelegate is effectively the same as NSControlTextEditingDelegate, just with a different name, but it's possible that new methods might be added to it in the future that are unrelated to NSControlTextEditingDelegate, so that's probably why it's designed as a separate protocol.
Related
Looking at Apples header file NSView.h
I see this line
#protocol NSDraggingSource;
Later I see
#interface NSView : NSResponder <..., NSDraggingDestination,...>
So what protocols does the NSView conform to?
These are two completely different issues:
The #protocol is simply a "forward declaration" of a protocol called NSDraggingSource. This effectively says "there exists a protocol called NSDraggingSource and should be accepted syntactically as a protocol reference." The requirements of the protocol are unknown until you come across the actual protocol definition, though.
These forward declarations are often used when you want to specify that a property or method parameter must conform to a protocol, but at this point you aren't concerned about what the protocol requirements are. The protocol definition must be defined by the time you get to the #implementation of these methods and properties, but at the point of the #interface we merely need to know that a protocol of that name exists.
You ask why they didn't just add NSDraggingSource to the list of protocols to which NSView conforms. The mere presence of the #protocol forward declaration has nothing to do with whether NSView conforms or not.
In this case, it's not NSView that conforms to this protocol, but rather the source parameter to one of NSView's methods, namely beginDraggingSessionWithItems. So, in the #interface we need to know that a protocol of that name exists, but we won't worry about the specific requirements of that protocol until we get to the #implementation.
Trying to understand protocols and their use... having a hard time of it. The more I read, the less I am able to even formulate questions about them. I've read the statement "a protocol is a contract" a hundred times, but it just doesn't click.
I "only" want to develop really simple apps, so assume that I would not myself create a protocol for any of my classes.
I do want to use Apple's Scenekit framework, for example, and understand that I am required to implement some methods to do this - for example the SCNSceneRendererDelegate. The compiler enforces this, and it knows to do that because in my header file I have inserted:
#interface AAPLGameViewController : UIViewController <SCNSceneRendererDelegate>
the bit between the angle brackets specifically.
For the prototypes of the functions I have to implement, I go look for a
#protocol
...
#end
section in the SCNSceneRendererDelegate header file.
But now I've come across some #protocol sections (e.g. in the UIApplication header file) that contain #properties!! I thought #protocol was only about implementing certain methods, what is a property doing there?
I also came across in one of the answers here that specifying a protocol name when creating an instance of an object allows me to use objects that I know nothing about. I would be very grateful to get a few simple practical examples of where this would be useful.
And finally, in Java, the counterpart to (Obj-C) #protocols are called interfaces. Is there a counterpart in Java to (Obj-C) #interface?
Thanks much, cheers.
Adhering to a protocol tells other classes that your class has a specific set of characteristics. Usually protocols are used to define what methods a specific class should have so that it can be the delegate of another class, meaning the class adopting the protocol is guaranteed to have defined the required methods that the delegate class will call in a callback. If the protocol defines a property, it simply means any classes adopting the protocol are expected to also have that property. For example:
#protocol MyProtocol <NSObject>
#required
#property (readonly) NSString *title;
#optional
- (void) someMethod;
#end
I can now define a method anywhere that takes an object conforming to MyProtocol and safely access the title property because it is guaranteed to exist for all classes adopting MyProtocol.
-(void)printTitleOfObject:(id<MyProtocol>)object {
NSLog(#"%#", object.title);
}
So even though id can be any object, since we know that it conforms to our protocol we know that it has the title property. When people say "a protocol is a contract", what they mean is even if we don't know specifically what class is adopting the protocol, we know it at least has the methods and properties listed as required in the protocol. Specifying a protocol for a class allows us to know some information about it, even if we don't know what class it is.
Apple has written documentation for protocols they've written, like the SCNSceneRendererDelegate you mentioned in your question.
But now I've come across some #protocol sections (e.g. in the
UIApplication header file) that contain #properties!! I thought
#protocol was only about implementing certain methods, what is a
property doing there?
Properties are methods. A property declaration is simply a declaration for a getter-setter method pair (or if a readonly property, just a getter method), and allows the compiler to turn a dot notation access into a call to this getter and setter. That's all a property is. How the getter/setter is implemented (whether manually implemented or synthesized), and whether it reflects an underlying value or not (or is computed from other things) are private implementation details of the getter/setter methods.
I'm going through the book about Cocoa and Objective C ("Aaron Hillegass, Adam Preble - Cocoa Programming for Mac OS X - 2012") and when I did the example with NSTableView, I noticed that it really doesn't matter if I define my class as conforming to NSTableViewDataSource, NSTableViewDelegate protocols or omit them, only methods matter. (looks like sort of duck typing)
That is, the application works fine with both definitions:
#interface SpeakLineAppDelegate : NSObject <NSApplicationDelegate, NSSpeechSynthesizerDelegate, NSTableViewDataSource, NSTableViewDelegate>
and
#interface SpeakLineAppDelegate : NSObject <NSApplicationDelegate, NSSpeechSynthesizerDelegate>
It only yells at me at runtime if I don't implement 2 essential methods which are defined in NSTableViewDataSource, and in any case it doesn't matter at all if I put these protocols in class definition or not. So, what is the point in having them in the language? If they are only for documentation, we could put their names in comments as well, right? Or I'm missing something important here?
Protocol conformance can be checked at compile-time and runtime. Like most people said in the comments, protocol conformance is checked at compile-time. If you assign a type that doesn't conform to the protocol (other than id) to a variable of type bracketed with that protocol, the compiler should give you a warning. So in order to be able to pass an object that doesn't conform to a protocol to a parameter of that parameter type, you must have either 1) ignored a warning, or 2) gone through type id, which turns off static type checking.
The API you call also could (if it wanted to) check at runtime whether your objects formally conform to the protocol or not, using conformsToProtocol:. However, the convention in Cocoa is that the APIs never check for formal conformance to the protocol, but rather only check that it responds to a given selector when it needs to call it. This gives more flexibility to the user to, for example, use a class object (metaclasses can't formally conform to protocols, other than the ones conformed to by the root class) as a delegate.
In Objective-C / Cocoa how do I discover the messages I can implement in a delegate class?
From what I have read in the documentation a class will only allow certain chosen messages to be handled via a delegate but so far have found difficulty finding a list of messages for a class.
To ask the question another way, if I created a delegate for NSApplication, which messages are available for me to handle?
The documentation for NSApplication states a delegate
responds to certain messages on behalf of NSApp.
The documentation then goes onto say
NSApplication defines over twenty delegate methods that offer opportunities for modifying specific aspects of application behavior.
but as far as I can see it fails to list these methods / messages so how do I know which ones will be called from my delegate?
The delegate is usually supposed to conform to a protocol declared for that purpose, e.g. NSApplicationDelegate. If it's not clearly spelled out already, you can often find the name of the appropriate protocol by looking at the type of the delegate property (in this case, id<NSApplicationDelegate>). You can check the documentation for details on the methods, or the #protocol declaration in the appropriate header file for specifics on which methods are available and which are required or optional.
There are some cases where the object does not define a protocol for its delegate, for example NSURLConnection. In this case, you just have to follow the documentation of the class with respect to what it expects of its delegate.
In either case, it is completely up to the class when it sends a message to the delegate and what the semantics of any message are.
These methods are described in the NSApplicationDelegate documentation:
http://developer.apple.com/library/mac/#documentation/cocoa/reference/NSApplicationDelegate_Protocol/Reference/Reference.html
One quick note that is that it is useful to understand the difference between formal and informal protocols. Also formal protocols have optional methods, which needn't be called.
When you write your own protocol you will want to check -respondsToSelector: before sending optional/informal methods.
formal protocols are defined like...
#protocol SomeProtocol <NSObject>
-(void)someMethod:(id)sender;
-(void)someOtherMethod:(NSString*)aString;
#property(nonatomic,retain) someProperty;
#optional
-(BOOL)someOptionalMethod;
#end
and are adopted like...
#interface SomeClass : NSObject <SomeProtocol> {
}
#end
this tells the compiler that you are adopting SomeProtocol, and you wont be required to declare you methods for the protocol in the .h file, it also tell the compiler to warn you if you haven't implemented all of the required methods.
for informal protocols you don't adopt them syntactically, but you will need to declare your methods in the .h file.
In Objective-C, I can add methods to existing classes with a category, e.g.
#interface NSString (MyCategory)
- (BOOL) startsWith: (NSString*) prefix;
#end
Is it also possible to do this with protocols, i.e. if there was a NSString protocol, something like:
#interface <NSString> (MyCategory)
- (BOOL) startsWith: (NSString*) prefix;
#end
I want to do this since I have several extensions to NSObject (the class), using only public NSObject methods, and I want those extensions also to work with objects implementing the protocol .
To give a further example, what if I want to write a method logDescription that prints an object's description to the log:
- (void) logDescription {
NSLog(#"%#", [self description]);
}
I can of course add this method to NSObject, but there are other classes that do not inherit from NSObject, where I'd also like to have this method, e.g. NSProxy. Since the method only uses public members of protocol , it would be best to add it to the protocol.
Edit: Java 8 now has this with "virtual extension methods" in interfaces: http://cr.openjdk.java.net/~briangoetz/lambda/Defender%20Methods%20v4.pdf. This is exactly what I would like to do in Objective-C. I did not see this question earning this much attention...
Regards,
Jochen
Short answer: No.
Long answer: how would this work? Imagine you could add methods to existing protocols? How would this work? Imagine we wanted to add another method to NSCoding, say -(NSArray *) codingKeys; This method is a required method that returns an array of the keys used to encoding the object.
The problem is that there are existing classes (like, say NSString) that already implement NSCoding, but don't implement our codingKeys method. What should happen? How would the pre-compiled framework know what to do when this required message gets sent to a class that does not implement it?
You could say "we can add the definition of this method via a category" or "we could say that any methods added via these protocol categories are explicitly optional". Yes, you could do this and theoretically get around the problem I've described above. But if you're going to do that, you might as well just make it a category in the first place, and then check to make sure the class respondsToSelector: before invoking the method.
While it's true that you can't define categories for protocols (and wouldn't want to, because you don't know anything about the existing object), you can define categories in such a way that the code only applies to an object of the given type that has the desired protocol (sort of like C++'s partial template specialization).
The main use for something like this is when you wish to define a category that depends on a customized version of a class. (Imagine that I have UIViewController subclasses that conform to the Foo protocol, meaning they have the foo property, my category code may have need of the foo property, but I can't apply it to the Foo protocol, and if I simply apply it to UIViewController, the code won't compile by default, and forcing it to compile means someone doing introspection, or just screwing up, might call your code which depends on the protocol. A hybrid approach could work like this:
#protocol Foo
- (void)fooMethod
#property (retain) NSString *foo;
#end
#implementation UIViewController (FooCategory)
- (void)fooMethod {
if (![self conformsToProtocol:#protocol(Foo)]) {
return;
}
UIViewController<Foo> *me = (UIViewController<Foo>*) self;
// For the rest of the method, use "me" instead of "self"
NSLog(#"My foo property is \"%#\"", me.foo);
}
#end
With the hybrid approach, you can write the code only once (per class that is supposed to implement the protocol) and be sure that it won't affect instances of the class that don't conform to the protocol.
The downside is that property synthesis/definition still has to happen in the individual subclasses.
extObjC has the NEATEST stuff you can do with Protocols / Categories... first off is #concreteprotocol...
Defines a "concrete protocol," which can provide default implementations of methods within protocol.
An #protocol block should exist in a header file, and a corresponding #concreteprotocol block in an implementation file.
Any object that declares itself to conform to this protocol will receive its method implementations, but only if no method by the same name already exists.
MyProtocol.h
#protocol MyProtocol
#required - (void)someRequiredMethod;
#optional - (void)someOptionalMethod;
#concrete - (BOOL)isConcrete;
MyProtocol.m
#concreteprotocol(MyProtocol) - (BOOL)isConcrete { return YES; } ...
so declaring an object MyDumbObject : NSObject <MyProtocol> will automatically return YES to isConcrete.
Also, they have pcategoryinterface(PROTOCOL,CATEGORY) which "defines the interface for a category named CATEGORY on a protocol PROTOCOL". Protocol categories contain methods that are automatically applied to any class that declares itself to conform to PROTOCOL." There is an accompanying macro you also have to use in your implementation file. See the docs.
Last, but NOT least / not directly related to #protocols is
synthesizeAssociation(CLASS, PROPERTY), which "synthesizes a property for a class using associated objects. This is primarily useful for adding properties to a class within a category. PROPERTY must have been declared with #property in the interface of the specified class (or a category upon it), and must be of object type."
So many of the tools in this library open (way-up) the things you can do with ObjC... from multiple inheritance... to well, your imagination is the limit.
It isn't really meaningful to do so since a protocol can't actually implement the method. A protocol is a way of declaring that you support some methods. Adding a method to this list outside the protocol means that all "conforming" classes accidentally declare the new method even though they don't implement it. If some class implemented the NSObject protocol but did not descend from NSObject, and then you added a method to the protocol, that would break the class's conformance.
You can, however, create a new protocol that includes the old one with a declaration like #protocol SpecialObject <NSObject>.
I think you may be mixing up terms here and there. Extensions, Categories, Protocols, Interfaces and Classes are all different things in Objective-C. In The Objective-C 2.0 Language Apple describes the differences very well, including the benefits and drawbacks to using categories and extensions.
If you think about it, what is a "Category" or "Extension" in the conceptual sense? It's a way of adding functionality to a Class. In Objective-C, protocols are designed to have no implementation. Therefore, how would you add or extend the implementation of something that doesn't have implementation to begin with?
if you're already writing a category, why not just add in the protocol definition in the header right after the category definition?
i.e.
#interface NSString (MyCategory)
- (BOOL) startsWith: (NSString*) prefix;
#end
#protocol MyExtendedProtocolName <NSString>
//Method declarations go here
#end
this way any class that imports the category header will also get the protocol definition, and you can add it into your class..
#interface MyClass <OriginalProtocol,MyExtendedProtocolName>
also, be careful when subclassing NSString, it's a cluster and you may not always get the behaviour you're expecting.
Adam Sharp posted a solution that worked for me.
It involves 3 steps:
Defining the methods you want to add as #optional on a protocol.
Making the objects you want to extend conform to that protocol.
Copying those methods into those objects at runtime.
Check out the link for the full details.