7

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 *?

3 Answers 3

14

You reference it as:

id<TheNameOfTheProtocol> aVariableToThatProtocol;

Or if a message wants a (Protocol *) object:

[myObject conformsToProtocol:@protocol(TheNameOfTheProtocol)];
Sign up to request clarification or add additional context in comments.

5 Comments

Just curious, any reason why a protocol "type" must be used with an "id?" Coming from a C# background, it's a little easier to visualize a interface reference since you just treat its declaration similar to a class reference (i.e. IProtocol protocol;).
@5StringRyan I don't know the reasoning, but the id type is the general type for any object, even if it is not an NSObject. One advantage to this syntax is it allows multiple protocols. You can do something along the lines of id<Readable, Writable> to express that the object conforms to both protocols. Or, if your protocol does not conform to NSObject, but a class instance you reference does you can do the following: id<MyProtocol, NSObject>.
@5StringRyan the type does not need to be id. example: NSArray<NSCopying>* var = [NSArray array]; is legal definitely useful at times. you can also write NSArray<NSObject,NSCopying>* var = [NSArray array]; sooo... it's certainly a good way to inject some type safety. (the examples are silly - they only demonstrate the syntax)
@Justin - Awesome, I've been using id for a while now with my protocols, there are quite a few places in my code where it would be nice to provide the type safety.
yup, id is ubiquitous - it probably took me a few years before i figured it out or stumbled across it.
5

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.

Comments

2

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;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.