views:

28

answers:

1

I am writing my first lines in objective-c for an iPhone app.

This is the code:

/* ViewController.h */
@protocol ImageFlowScrollViewDelegate;

@interface ViewController : UIViewController<ImageFlowScrollViewDelegate> {
    NSMutableArray *characters;
    UILabel *actorName;
}

/* ViewController.m */
#import "ImageFlowScrollView.h"
@implementation IMDBViewController
/* methods here */

/* ImageFlowScrollView.h */
@protocol ImageFlowScrollViewDelegate;

@interface ImageFlowScrollView : UIScrollView<UIScrollViewDelegate> {

    NSMutableArray *buttonsArray;
    id<ImageFlowScrollViewDelegate> imageFlowScrollViewDelegate;

}

@property(nonatomic, assign)id<ImageFlowScrollViewDelegate> imageFlowScrollViewDelegate;

- (id)initWithFrame:(CGRect)frame imageArray:(NSArray *) anArray;
- (void)focusImageAtIndex:(NSInteger) index;

@end


@protocol ImageFlowScrollViewDelegate<NSObject>

@optional
- (void)imageFlow:(ImageFlowScrollView *)sender didFocusObjectAtIndex: (NSInteger) index;
- (void)imageFlow:(ImageFlowScrollView *)sender didSelectObjectAtIndex: (NSInteger) index;
@end

Doing this, I get a

warning: no definition of protocol 'ImageFlowScrollViewDelegate' is found

I can fix it using:

#import "ImageFlowScrollView.h"

@interface IMDBViewController : UIViewController<ImageFlowScrollViewDelegate> {
    NSMutableArray *characters;
    UILabel *actorName;
}

but I would like to know why the forward declaration approach is giving me a warning.

+1  A: 

The forward declaration defines the symbol so the parser can accept it. But when you try to use the protocol (or class) - as you do by conforming to the protocol - the compiler needs it's definition to know the layout and size of the resulting object.

In addition, you can forward a class or protocol when you are only using it in the class (in an ivar for example). The compiler then only needs to know the existence of the symbol. But when making use of the class (in the implementation file), the methods need to be declared before use hence the need to include the declaration.

For example :

/* AViewController.h */

@class AnotherClass;

@interface AViewController : UIViewController {
    AnotherClass* aClass; //only need the declaration of the name
}

@end

/* AViewController.m */

#import "AnotherClass.h"

@implementation AViewController

- (void) useAnotherClass {
     [AnotherClass aMessage]; //aMessage needs to be declared somewhere, hence the import
}

@end

In addition, you already know that you must provide actual implementations in order to link your program.

David
Ok, so the forward declaration for protocols are just used for fields, but not for implementations.
Macarse
Yes, you are correct. Forward declarations in objective-c (and in C++) are a common way to reduce header file dependencies.
David