Protocol methods depending on each other - objective-c

I have run into this weird situation where I have two protocols and both have methods with parameters that must conform to the other protocol. Sounds confusing, so heres some code:
#protocol ProtocolB <NSObject>
#required
-(void)methodB:(id<ProtocolA>)parameter;
#end
#protocol ProtocolA <NSObject>
#required
-(void)methodA:(id<ProtocolB>)parameter;
#end
The compiler says: "Cannot find protocol declaration for ...". Depending on which protocol comes first, it's either ProtocolA or ProtocolB.
Putting them in different files didn't seem to solve this problem.
Any ideas how I can do this without a (major and possibly complicated) redesign?

Forward declaration of protocol might do. Add #protocol ProtocolA; before ProtocolB

Related

What does #protocol mean?

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.

Protocol declaration ends with semicolon?

#protocol ZZCapturePipelineDelegate;
#protocol ZZMediaManagerProtocol;
#protocol ZZCapturePipelineProtocol <NSObject>
...
#end
I understand ZZCapturePipelineProtocol is the protocol being declared here. However I have never seen the syntax with multiple #protocol in one file. Since the first two protocols ends with semicolon, I am assuming the their purposes are to import or reference to their respective .h files?
The two ones are called forward declarations - i.e. you inform the compiler that the protocols exist, but without importing the headers where they were defined. This improves the build time because the compiler doesn't have to insert+compile the content of other headers.
You can find out more details here.

Is it a good practice to force developer to comply with a protocol in objective C?

I am developing a simple set of reusable code. I have created a protocol to group a set of methods and ask the user at run time for data.
I think that setting a delegate would be mandatory. Can I force the developer at runtime to set the delegate by throwing an assert stating the reason?
Is this a good practice to enforce the user of my classes by using asserts? Does it have a design level flaw?
First the "good practice" question:
Don't make methods required unless they actually are.
Don't make methods optional if they aren't.
Not a critical one, more of an opinion
Provide a method initWithDelegate: if a delegate is required
I often come across data structures where I don't know that there is a delegate pattern until I investigate. With the specific init method, I'm made aware of it earlier.
You can cause warnings at compile time by simply adding the #required indicator to your protocol:
#protocol SuperAwesomeProtocol <NSObject>
#required
-(void) requiredMethod1;
-(void) requiredMethod2;
#optional
-(void) optionalMethod1;
-(void) optionalMethod2;
#end
//and making your delegate specific:
#property (nonatomic, assign) id<SuperAwesomeProtocol> delegate;
You can still cause runtime asserts with:
if (!delegate || ![delegate respondsToSelector:#selector(requiredMethod1)])
{
//Assertion failure
}
Yes I think it is good practice to use protocol in the application..
Protocols declare methods that can be implemented by any class.
Below are the situation in which use of protocol is good.
To declare methods that others are expected to implement
To declare the interface to an object while concealing its class
To capture similarities among classes that are not hierarchically
related

Category on NSObject implementing protocol causes Unimplemented Method warnings

If I define a subprotocol of the NSObject protocol with extra methods, then define and implement a category on NSObject that declares conformance to that protocol, I get warnings on compilation. The compiler complains that my NSObject category doesn't implement all the methods declared in the NSObject protocol.
I don't understand why this is the case. The NSObject class (in <Foundation/NSObject.h> declares that it conforms to the NSObject protocol (and, redundantly, that it implements these methods) - shouldn't that suffice?
What's the cause of the problem here?
Sample code - if you compile this, you'll see warnings on the NSObject (CategoryToImplementMyProtocol) implementation:
#protocol MyProtocol <NSObject>
- (void)myMethod;
#end
#interface NSObject (CategoryToImplementMyProtocol) <MyProtocol>
#end
#implementation NSObject (CategoryToImplementMyProtocol)
- (void)myMethod
{
NSLog("A la peanut butter sandwiches!");
}
#end
I found a couple of questions addressing this, but all the answers were of the "do this workaround!" variety, not that "this is the cause of the problem" variety (or just plain wrong, despite being accepted...). I know I can work around this. I'd really like to understand why it fails.
The problem is that you are declaring adoption of the <NSObject> protocol again. The way protocols work in Objective-C (for better or for worse) is that a category implementation must implement all of the protocols that are specified in its interface.
In addition, protocol conformance is nominal rather than structural in Objective-C. That is to say, for a class to respond to the correct methods is not enough for it to have adopted that protocol.
Edit: Seems the example code has been changed, and I guess my answer isn't really relevant anymore.

Can a category simultaneously implement a protocol?

If a category I'm creating for a class adds methods that also fulfill the contract set out by a protocol, I'd like to flag that category class as implementing the protocol, and thereby indicate to the Obj-C pre-processor that the class effectively implements the protocol as well.
Example delegate (for clarity, thanks Ole!):
#protocol SomeDelegate <NSObject>
- (void)someDelegateMessage;
#end
Example category:
#interface NSObject (SomeCategory) <SomeDelegate>
- (void)someDelegateMessage;
#end
And with an otherwise typical implementation
#implement NSObject (SomeCategory)
- (void)someDelegateMessage {}
#end
When I actually try this, I get a warning for each NSObject method:
warning: incomplete implementation of category 'SomeCategory'
warning: method definition for '-description' not found
...
warning: method definition for '-isEqual:' not found
warning: category 'SomeCategory' does not fully implement the 'NSObject' protocol
Works fine if I remove <SomeDelegate> from the declaration, but of course NSObject isn't recognized as a SomeDelegate
A workaround is to declare the protocol on a category with no implementation, and implement the method in a different category, e.g.:
#interface NSObject (SomeCategory) <SomeDelegate>
- (void)someDelegateMessage;
#end
#implementation NSObject (SomeCategory_Impl)
- (void)someDelegateMessage {}
#end
If you do this, NSObject will be considered to conform to <SomeDelegate> at compile time, and runtime checks for someDelegateMessage will succeed. However, conformsToProtocol: runtime checks will fail.
Of course, you should file a bug requesting that methods declared on the core class don’t generate warnings.
Any chance your protocol declaration includes the NSObject protocol? Like this:
#protocol SomeDelegate <NSObject>
...
That's where the warnings are coming from because now your category does not implement the full protocol. In the test code I just typed up, removing NSObject from the protocol removes the compiler warnings.
If you want the compiler to shut up about sending <NSObject> messages (and its important that you remember that thats the protocol name, not the class name) then just use 'id' variables, not 'id' since thats you explicitly telling the compiler "This is an object which only implements the SomeDelegate protocol".
Alternately, use NSObject as your variable type instead.