«

»

Jul
04

Forward Declaration

In the spirit of keeping this as a personal blog to record my own progress, I have decided to limit my posts to observations and overviews, instead of writing any form of tutorials or guides.

For my first insight, the sorcerer in me tried to blast through creation of a series of interconnected controllers while working in Objective-C a little while ago. I know that Obj-C uses #import instead of my more familiar #include because #import keeps track of what is already brought in.

In my preferred C, I will begin a header to a common source file with the following to ensure I never load multiple versions of the same header:

#ifndef settings
#define settings
...
#endif

The beautiful aspect of #import is that it does this automatically, so you can just sort of pave through thinking about design a little and #import everything, knowing that it’ll only do one load of the code therein.

My problem here comes from a subconscious reliance on this to solve all header-releated problems; which, in this case, involved circular dependencies.

My current project has the following model in place, which I shall attempt to present the relevant bits to my problem in pseudocode.

MyAppDelegate -> MainViewController -> SettingsViewController -> PickerViewController

MyAppDelegate.h
--- #import "MainViewController.h"

MainViewController.h
--- #import "MyAppDelegate.h"
--- #import "SettingsViewController.h"

SettingsViewController.h
--- #import "MyAppDelegate.h"
--- #import "PickerViewController.h"

PickerViewController.h
--- #import "MyAppDelegate.h"

Now, looking it it sort of abstracted shows immediately that MyAppDelegate depends on MainViewController, which depends on MyAppDelegate, which depends on MainViewController, ad infinitum.  This is a problem that a wizard would have discovered long before putting quill to Xcode, but it’s something that took me a bit of work to discover.  Implementing this, I received two errors on MyAppDelegate.h, both of which read:

"MyAppDelegate.h:14: error: expected specifier-qualifier-list before 'MainViewController'"

Now, I’ve been coding for a while, but that struck me as mostly cryptic.  What this basically refers to is the lack of a definition for MainViewController at each of the two places in the header where I reference it.  This had me floored for a while because the #import “MainViewController.h” line is quite present and MainViewController.h is a complete header.

As it turns out, Objective-C will, at some stage in the buld process, recognize the cyclic dependency and simply refuse to play that game, which robs my MyAppDelegate of the loaded definition for MainViewController, triggering this particular error.  Objective-C, like C++, does have a rather nice solution for this though: Forward Declaration.

Since this is a compiled language, you don’t necessarily need to have all of your eggs defined in the master basket before first refering to something in your code.  In this particular case, the compiler is plenty happy enough knowing that something will be defined at a later stage, when it’s actually needed.  In this case, I’m not using anything that requires knowledge of precisely how MainViewController works, all I’m doing is telling MyAppDelegate that it has a variable available to it of the type MainViewController.  Beacause all I need here is knowledge of it’s existence, I can forward define MainViewController in the header and leave the actual import to the source ‘.m’ file.

MyAppDelegate.h
--- @class MainViewController.h; // Forward Declaration Statement

MyAppDelegate.m
--- #import "MyAppDelegate.h"
--- #import "MainViewController.h"

MainViewController.h
--- #import "MyAppDelegate.h"
--- #import "SettingsViewController.h"

SettingsViewController.h
--- #import "MyAppDelegate.h"
--- #import "PickerViewController.h"

PickerViewController.h
--- #import "MyAppDelegate.h"

Now I can use a definition for MainViewController in the header of MyAppDelegate and use a definition for MyAppDelegate in MainViewController without any circular references.

- Kevin, Chaotic Sorcerer, Initiate Coder

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>