objc_getProtocol() returns NULL for `NSApplicationDelegate"? - objective-c

I'm trying to use the objc_getProtocol() function to get a reference to the struct representing the NSApplicationDelegate protocol:
Protocol *protocol = objc_getProtocol("NSApplicationDelegate");
However, for some reason, this always returns NULL.
Other protocols such as NSObject, NSCoding, NSTableViewDelegate, and NSTableViewDataSource work fine.
Is there something special about NSApplicationDelegate, or am I doing something wrong?

Found the answer in the Apple docs:
http://developer.apple.com/library/ios/#DOCUMENTATION/Cocoa/Conceptual/ObjectiveC/Chapters/ocProtocols.html#//apple_ref/doc/uid/TP30001163-CH15
The compiler creates a protocol object for each protocol declaration it encounters, but only if the protocol is also:
Adopted by a class,
Or referred to somewhere in source code (using
#protocol())

Related

What is the point in having protocols if they are not checked?

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.

Protocol on method declaration?

I'm starting to use the Nimbus framework and I just ran across this syntax for the first time. It looks like they are using some kind of protocol in the method declaration and then when declaring a variable. I've only seen protocols used in the header file right after the class name so this is completely new to me.
- (UIView<NIPagingScrollViewPage>*)pagingScrollView:(NIPagingScrollView *)pagingScrollView pageViewForIndex:(NSInteger)pageIndex {
Also:
UIView<NIPagingScrollViewPage>* pageView = nil;
What exactly does this mean? Why are they using this format?
That declaration makes sure that the UIView returned conforms to the NIPagingScrollViewPage protocol. The compiler will emit a warning if the method tries to return an object that isn't declared to conform.
A more common usage of that syntax would be a delegate, as you'll allow any class that conforms to the protocol to be the delegate, so that syntax is used to make sure the class conforms to the protocol.
-(void)setDelegate:(id<SampleDelegate>)del //Makes sure that del conforms to the protocol SampleDelegate, the compiler will emit a warning
This is just the way to declare that it is confirming to that protocol. Otherwise warnings will be shown. Then you have to use id.
So It is always a good practice to use (datatype<protocol>*)variableName

How to reference Protocol in Objective-C?

I know the directive for a protocol is #protocol just like #selector, but what is the "type" for referencing a Protocol (eg. SEL for #Selector)? In MacOSX stack, it's Protocol *?
You reference it as:
id<TheNameOfTheProtocol> aVariableToThatProtocol;
Or if a message wants a (Protocol *) object:
[myObject conformsToProtocol:#protocol(TheNameOfTheProtocol)];
id <YourProtocol> delegate(which is used to reference the protocol)?
I referred to the apple's official DOC, and found an simple example to refer to other protocols in a protocol:
#import "B.h"
#protocol B; // To break the recursive cycle, you must use the #protocol directive to make a forward reference to the needed protocol instead of importing the interface file where the protocol is defined
#protocol A
- foo:(id <B>)anObject;
#end
where protocol B is declared like this:
#import "A.h"
#protocol B
- bar:(id <A>)anObject;
#end
Note that using the #protocol directive in this manner simply informs the compiler that B is a protocol to be defined later. It doesn’t import the interface file where protocol B is defined.
And here're more things you'd like to know about protocol:
In many ways, protocols are similar to class definitions. They both declare methods, and at runtime they’re both represented by objects—classes by instances of Class and protocols by instances of Protocol. Like class objects, protocol objects are created automatically from the definitions and declarations found in source code and are used by the runtime system. They’re not allocated and initialized in program source code.
Source code can refer to a protocol object using the #protocol() directive—the same directive that declares a protocol, except that here it has a set of trailing parentheses. The parentheses enclose the protocol name:
Protocol *myXMLSupportProtocol = #protocol(MyXMLSupport);
This is the only way that source code can conjure up a protocol object. Unlike a class name, a protocol name doesn’t designate the object—except inside #protocol().
And what's more, the protocol is possible to check whether an object conforms to a protocol by sending it a conformsToProtocol: message:
if ( ! [receiver conformsToProtocol:#protocol(MyXMLSupport)] ) {
// Object does not conform to MyXMLSupport protocol
// If you are expecting receiver to implement methods declared in the
// MyXMLSupport protocol, this is probably an error
}
The conformsToProtocol: test is like the respondsToSelector: test for a single method, except that it tests whether a protocol has been adopted (and presumably all the methods it declares implemented) rather than just whether one particular method has been implemented. Because it checks for all the methods in the protocol, conformsToProtocol: can be more efficient than respondsToSelector:.
The conformsToProtocol: test is also like the isKindOfClass: test, except that it tests for a type based on a protocol rather than a type based on the inheritance hierarchy.
It's the same as on OS X:
Protocol * p = objc_getProtocol("UITableViewDataSource");
It's declared in <objc/runtime.h>:
typedef struct objc_object Protocol;

Pass a protocol as a method argument

First let me explain what I don't mean. I don't want to type an argument to a protocol:
-(void)someMethod:(id<SomeProtocol>)someArgument;
What I do want to is to pass a protocol to a method in the same way I can pass a Class to a method (The following is incorrect, but it hopefully explains what I want to do):
-(void)someMethod:(Protocol)someArgument;
I would then like to be able to use the Protocol to check whether a set of objects implement it.
If you know the name of a protocol at coding-time, use #protocol(SomeProtocol) to get a pointer to that protocol, similar to how you'd use #selector(x).
Beyond that, you just refer to protocols with the class identifier Protocol -- so you're method declaration would look like:
-(void)someMethod:(Protocol*)someArgument
You can see an example in the docs for NSObject conformsToProtocol:
http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/Reference/Reference.html#//apple_ref/occ/clm/NSObject/conformsToProtocol:
Protocol is a class, so you just write - (void)someMethod:(Protocol *)someArgument like with any other object type. You can see this in the declaration for conformsToProtocol::
+ (BOOL)conformsToProtocol:(Protocol *)aProtocol
- (void) executeRequest:(id<Protocol1>)request andCompletion:(id<Protocol2>)response
the only way to pass protocol into an argument
because id<..> means it needs to conform to that protocol before pass throw the argument
I don't recommend using protocol. It will obscure which interface your code actually relies on. Use id<yourprotocol>*. This is actually how the cocoa frameworks pass protocols. Forgive the use of words if I don't it thinks I'm trying to do HTML.

Introspect parameter of type: id to decide whether it is a class or a protocol

I have the following method:
-(void)SomeMethod:(id)classOrProtocol;
It will be called like this:
[self someMethod:#protocol(SomeProtocol)];
Or
[self someMethod:[SomeClass class]];
Within the method body I need to decide if |classOrProtocol| is:
Any Class(Class) OR Any Protocol(Protocol) OR Anything else
[[classOrProtocol class] isKindOfClass: [Protocol class]]
Results in a (build)error:
Receiver 'Protocol' is a forward class and corresponding #interface may not exist
So how can I tell a Protocol from a Class from anything else?
In Objective-C 2 (i.e. unless you use 32 bit runtime on OS X) Protocol is defined to be just a forward class, see /usr/include/objc/runtime.h. The real interface is nowhere declared. You can try to include /usr/inlcude/objc/Protocol.h by saying
#import <objc/Protocol.h>
but as is written there, no method is publicly supported for an instance of Protocol. The only accepted way to deal with Protocol instances is to use runtime functions, given in Objective-C Runtime Reference. It's not even publicly defined whether Protocol is a subclass of anything, and it's not even stated that it implements NSObject protocol. So you can't call any method on it.
Of course you can use the source code of the runtime to see what's going on. Protocol inherits from Object (which is a remnant from pre-OpenStep NeXTSTep), not from NSObject. So you can't use the familiar methods for NSObject-derived objects, including Class of NSObject-derived objects. See the opensourced implementations of Protocol.h and Protocol.m. As you see there, the class Protocol itself doesn't do anything, because every method just casts self to protocol_t and calls a function. In fact, as can be seen from the function _read_images and others in objc-runtime-new.mm, the isa pointer of a Protocol object is set by hand when the executable and libraries are loaded, and never used.
So, don't try to inspect whether an id is a Protocol or not.
If you really need to do this, you can use
id foo=...;
if(foo->isa==class_getClass("Protocol")){
...
}
But, seriously, don't do it.
This is not an issue 'caused by inability to determine whether it's class or protocol. The error is 'caused by missing interface of Protocol class. Make sure you import Protocol.m at the top of your implementation file where you're testing argument's type.
You can also try using NSClassFromString() function which will return Class object or nil. Do note though that if nil is returned it doesn't mean that argument is protocol. It just means that it could be undefined class too!
There is also method NSProtocolFromString which returns appropriate results - Protocol for protocol and nil for undefined protocol.