Using @class to get access to a delegate protocol declaration
Asked Answered
T

5

8

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.

Traveller answered 21/10, 2013 at 16:25 Comment(0)
P
6

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.

Puny answered 21/10, 2013 at 16:31 Comment(1)
Not to nick pits, but to be more precise: you can forward-declare a protocol, but not if you are declaring a class that conforms to that protocol (in that header file). If the protocol is only needed for a method return or parameter type, it's fine to declare it (and you use "@protocol MyProtocol;" instead of "@class MyProtocol;" to do so).Lusatia
M
11

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.

Mucor answered 21/10, 2013 at 16:37 Comment(0)
P
6

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.

Puny answered 21/10, 2013 at 16:31 Comment(1)
Not to nick pits, but to be more precise: you can forward-declare a protocol, but not if you are declaring a class that conforms to that protocol (in that header file). If the protocol is only needed for a method return or parameter type, it's fine to declare it (and you use "@protocol MyProtocol;" instead of "@class MyProtocol;" to do so).Lusatia
M
4

MyCustomClassDelegate is a protocol, not a class. Telling the compiler about the existence of MyCustomClass tells it nothing about the existence of the protocol.

Marishamariska answered 21/10, 2013 at 16:26 Comment(0)
D
2

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
Decemvir answered 21/10, 2013 at 16:29 Comment(2)
ehhh? I think he means the protocol is already declared in the class he is referencing so it does not need to be declared again.Roxieroxine
@Roxieroxine Ah, yes, he just needs to use #import rather than @class then. My mistake.Decemvir
D
0

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
Distress answered 19/5, 2018 at 13:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.