#protocol implementation in #interface in Objective-C - objective-c

I need to develop an application which has a interface which implements methods of 3 protocols.
Assume protocol A extends protocol B and protocol C, and interface implements protocol A.
This is how my code looks,
// This is in MyClass.h file
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "protocol_A"
#interface MyClass : NSObject <protocol_A>
{
}
#end
//This is MyClass.m file
#import "MyClass.h"
#implementation myClass
-(void)methodinA
{
NSLog(#"I'm in protocol_A");
}
}
-(void)methodinB
{
NSLog(#"I'm in protocol_B");
}
-(void)methodinC
{
NSLog(#"I'm in protocol_C");
}
#end
//This is protocol_A.h file
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "protocol_B.h"
#import "protocol_C.h"
#protocol protocol_A <protocol_B, protocol_C>
-(void)methodinA;
#end
//This is in protocol_B.h file
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#protocol protocol_B
-(void)methodinB;
#end
//This is in protocol_C.h file
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#protocol protocol_C
-(void)methodinC;
#end
i'm getting an exception , and my app is getting crashed...
***Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<MyClass 0X323nm31>setvalue:forundefinedKey:]:this class is not key value coding-compilant for the key window'.
Plz Tel me how to solve this problem??

So where you're getting this from (and the reason you're getting it 3 times) is you've got a mistake in your protocol definitions. You have:
//This is in protocol_C.h file
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#protocol protocol_C
{
}
-(void)methodinC;
#end
You can't declare class members in a protocol: only methods. Because of this, you don't need (and, as you've discovered) can't have the curly braces in the protocol definition. As such, you need this for your protocol definitions:
//This is in protocol_C.h file
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#protocol protocol_C
-(void)methodinC;
#end
Removing those should solve your issue.
When making new files, I always go through Xcode's new-class-files process, as it frequently gives you lots of convenient stuff. Here is the contents of a new protocol_D declaration fresh from Xcode:
#import <Cocoa/Cocoa.h>
#protocol protocol_D
#end
Hope this helps!
TL;DR: Protocol definitions can't have curly-braces anywhere in them.

Protocols generally go in a .h file; always go in a .h file if you plan on using them anywhere.
Just like everything else, you need to #import the .h file that contains the definition of the protocol before you use it.
So, in MyClass.h (it really should be capitalized -- Classes are always capitalized in Objective-C), #import the various protocol .h files.

Your protocol_A.h file declares conformance to protocol_B and protocol_C, yet you haven't imported the headers for protocol_B and protocol_C. This means that you are declaring conformance to protocols that as far as the compiler is concerned, don't exist in protocol_A.h. You need to import the headers:
In protocol_A.h:
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "protocol_B.h" //note these new imports
#import "protocol_C.h"
#protocol protocol_A <protocol_B, protocol_C>
-(void)methodinA;
#end

Also see Apple's Communicating with Objects, which discusses delegates, protocols, and selectors. Though its listed under Mac OS X, most (if not all) appears to apply to iOS also.

Related

Duplicate protocol definition warning

First, I have seen this question as well as this, but my problem is not addressed there.
I have a protocol ProtocolA defined in its own header file. Then I have two classes ClassA and ClassB which both conform to this protocol so the protocol-header is imported in their header files.
Now it gets a bit complicated. ClassA is used (and thus imported) in a third ClassC. This class conforms to a second protocol ProtocolB. This protocol also has its own header file where it uses and imports ClassB. So my ClassC imports (either directly or indirectly) both ClassA and ClassB (which both import ProtocolA). This gives me the following warning regarding ProtocolA:
warning: duplicate protocol definition of '…' is ignored
Why is this happening? It was my understanding that the #import macro was invented exactly for avoiding this kind of problems which we had with #include. How can I solve the issue without using an include guard? I can't really remove any of the imports.
EDIT: here is the code to illustrate the situation:
ProtocolA.h
#protocol ProtocolA <NSObject>
- (void)someMethod;
#end
ClassA.h
#import "ProtocolA.h"
#interface ClassA : NSObject <ProtocolA>
...
#end
ClassB.h
#import "ProtocolA.h"
#interface ClassB : NSObject <ProtocolA>
typedef enum Type {
TypeB1,
TypeB2
} TypeB;
...
#end
ProtocolB.h
#import "ClassB.h"
#protocol ProtocolB <NSObject>
- (TypeB)someMethod;
#end
ClassC.h
#import "ProtocolB.h"
#interface ClassC : NSObject <ProtocolB>
...
#end
ClassC.m
#import "ClassC.h"
#import "ClassA.h" // the warning appears here
#implementation ClassC
...
#end
do not Import ClassB in ProtocolB header, just use #class ClassB; in it and remove #import "ClassB"

Using #class to get access to a delegate protocol declaration

I've read that you should try to use #class in your header file instead of #import but this doesn't work when your #class contains a delegate protocol that you're trying to use.
MyView.h
#import <UIKit/UIKit.h>
#class MyCustomClass; // <-- doesn't work for MyCustomClassDelegate, used below
#interface MyView : UIView <MyCustomClassDelegate>
#end
I think I'm overlooking something, is there a way to get #class to work in this situation or is #import my only choice?
Edit: One work around for this is, of course, declaring your #import MyCustomClass and MyCustomClassDelegate in the private interface section of the .m file instead of the .h file.
you can use #protocol to forward declare a protocol if you only need it for variables such as this:
#protocol MyProtocol;
#interface MyClass {
id<MyProtocol> var;
}
#end
In your case the declared class is trying to conform to a protocol so the compiler must know about the protocol methods at this point in order to deduce weather or not the class conforms.
In this case, I think your options are to split the protocol into its own file and #import that header, or declare the protocol in that header above the class declaration that uses it.
You can only forward-declare a protocol in the same header file for usage in method return values or parameter types. In your case you want the class to conform to the protocol, so it won't work since it defines behavior that will be added to the class itself (i.e. the methods it will respond to).
Therefore, you must #import the protocol. For this reason, it is probably a good idea to split the protocol and class up into separate files. See this answer for more information.
MyCustomClassDelegate is a protocol, not a class. Telling the compiler about the existence of MyCustomClass tells it nothing about the existence of the protocol.
You will need to declare your delegate protocol before the class:
MyCustomClass.h:
#import <UIKit/UIKit.h>
#class MyCustomClass;
#protocol MyCustomClassDelegate <NSObject>
- (void)myCustomClass:(MyCustomClass *)customClass
didBlah:(BOOL)blah;
#end
#interface MyCustomClass : NSObject <MyCustomClassDelegate>
#end
And you cannot even use #protocol to forward-declare the delegate protocol; the compiler must see the complete declaration, therefore change your #class for an #import:
MyView.h:
#import <UIKit/UIKit.h>
#import "MyCustomClass.h" // the compile now knows what MyCustomClassDelegate is
#interface MyView : UIView <MyCustomClassDelegate>
#end
You cannot forward declare a protocol you conform to.
If you are using MyView as a MyCustomClassDelegate only in MyView's implementation, you can use Extension in MyView's .m file, such as this:
#import "MyView.h"
#import "MyCustomClassDelegate.h"
#interface MyView () <MyCustomClassDelegate> {
}
#end
#implementation MyView
...
#end

Xcode warns about missing protocol definition, even though #protocol is used

Since I had a import-cycle recently, I'm moving all #import statements (concerning my own files) from the header into the corresponding .m-file. I also added #class and #protocol forward-declarations to soothe the compiler. However, I still get he following warning:
Cannot find the protocol definition for 'MyCustomDelegate'.
As I said, there is an #protocol MyCustomDelegate before I use it in the #interface-Block. Interestingly this warning only occurs if the corresponding delegate is declared in another file (whose header is imported in the .m-file).
I read that one solution is to declare the delegate in a separate header file and import that file directly in the header of the class that implements the delegate. Is this really the way to go? Are there any other solutions? I think those delegates already bloated our code enough, now I should go on and even declare an own file for it?
Small sample code to better illustrate the problem:
NewFooController.h
#import <UIKit/UIKit.h>
#protocol NewFooControllerDelegate;
#interface NewFooController : UITableViewController
#property (nonatomic, weak) id<NewFooControllerDelegate> delegate;
#end
#protocol NewFooControllerDelegate
#end
HomeTableViewController.h
#import <UIKit/UIKit.h>
#protocol NewFooControllerDelegate;
// warning points to line below
#interface HomeTableViewController : UITableViewController <NewFooControllerDelegate>
#end
HomeTableViewController.m
#import "HomeTableViewController.h"
#import "NewFooController.h"
#implementation HomeTableViewController
#end
HomeTableViewController.h references the protocol, but it hasn't been declared yet.
If you import NewTaskController.h in HomeTableViewController.h before it attempts to use it, it should solve your problem.
Of course you can then remove the import from HomeTableViewController.m
Not sure if this is "best way", but try import header of class that implement protocol before class header file.
HomeTableViewController.m
#import "NewFooController.h"
#import "HomeTableViewController.h"
#implementation HomeTableViewController
#end
And you can remove protocol declaration in HomeTableViewController.h
#import <UIKit/UIKit.h>
#interface HomeTableViewController : UITableViewController <NewFooControllerDelegate>
#end

Import two objective-c protocols in each others file ends with compiler errors

there are two protocols, each in its own file:
// PMAService.h
#import <Foundation/Foundation.h>
#import "PMAPost.h"
#import "PMAServiceProcessingDelegate.h"
#protocol PMAService <NSObject>
-(void)setupService;
-(BOOL)processPost:(PMAPost *)post withDelegate:(id<PMAServiceProcessingDelegate>)delegate;
#end
// PMAServiceProcessingDelegate.h
#import <Foundation/Foundation.h>
#import "PMAPost.h"
#import "PMAService.h"
#protocol PMAServiceProcessingDelegate <NSObject>
-(void)successfullyProcessedPost:(PMAPost *)post by:(id<PMAService>)service;
-(void)notProcessedPost:(PMAPost *)post by:(id<PMAService>)service withError:(NSError *)error;
#end
each of the protocols needs the opposite for a method declaration. as soon as i create the import in each of the files, the compiler is not able to compile anymore since it tells me that it cannot find one of the protocols.
error messages for PMAService.h (for the #import statement of PMAServiceProcessingDelegate.h)
'PMAServiceProcessingDelegate.h' file not found
error messages for PMAServiceProcessingDelegate.h (one for each method declaration):
Cannot find declaration for 'PMAService'
Cannot find declaration for 'PMAService'
is there something i missed out? isn't it allowed to import protocols like this?
You have a circular dependency that you can solve using a forward declaration:
// PMAService.h
#import <Foundation/Foundation.h>
#import "PMAPost.h"
#protocol PMAServiceProcessingDelegate;
#protocol PMAService <NSObject>
-(void)setupService;
-(BOOL)processPost:(PMAPost *)post withDelegate:(id<PMAServiceProcessingDelegate>)delegate;
#end

#import in objective C: Am I doing this wrong?

Sorry, couldn't find a more appropriate title.
In My code I have two classes which should know of each others existence. So I use an instance variable which points to the other class. For that to work (I guess?) the other classes headers file should be imported so it knows which methods it has and such.
Here is my code (stripped down)
MainMenuController.h:
#import <Cocoa/Cocoa.h>
#import "IRCConnection.h"
#interface MainMenuController : NSViewController {
IRCConnection *ircConnection;
}
#property (strong) IRCConnection *ircConnection;
#end
IRCConnection.h:
#import <Foundation/Foundation.h>
#import "MainMenuController.h"
#interface IRCConnection : NSObject {
MainMenuController *mainMenuController;
}
#property (strong) MainMenuController *mainMenuController;
#end
As you can see they both import each other, but this creates an error (Unknown type name 'IRCConnection') in one, and in the other Unknown type name 'MainMenuController'.
However when the connection is just one way (e.g. only MainMenuController knows about IRCConnection) and thus there is only an import statement in one of the two, it works fine.
How can I have them to know about each other? In both ways.
Hope this question makes any sense.
you could remove the import from IRCConnection.h and use a #class statement instead.
like this:
#import <Foundation/Foundation.h>
#class MainMenuController;
#interface IRCConnection : NSObject {
then add a #import "MainMenuController.h" to IRCConnection.m
In the header, use forward declaration:
#class IRCConnection;
#interface MainMenuController : NSViewController {
IRCConnection *ircConnection; // ok
}
In the source file (.m), do #import.
You cannot have circular imports. You need to break them up, or introduce some forward declarations.