views:

1944

answers:

3

I'm having trouble with enum visibility in an Objective-C program. I have two header files, and one defines a typedef enum. Another file needs to use the typedef'd type.

In straight C, I would simply #include the other header file, but in Objective-C, it's recommended not to use #import between header files, instead using forward @class declarations as needed. However, I can't figure out how to forward-declare an enumeration type.

I don't need the actual enumerated values, except in the corresponding .m implementation file, where I can safely #import away. So how can I get the typedef enum to be recognized in the header?

+4  A: 

Go ahead and use #import. The only reason people recommend to use @class when possible is because it makes your code slightly faster to compile. However, there is no issue with #importing one .h file from another. In fact, you need to do this when extending another class.

Sebastian Celis
Is there any way the above is possible, without using #import? What about simply doing a `typedef int EnumName`?
Stephen Touset
I don't think so. See the link in gs's answer: http://stackoverflow.com/questions/71416/forward-declaring-an-enum-in-c
Sebastian Celis
+1  A: 

You'd have to either #import them anyway or create a separate header file containing only the typedef. Not importing header files in a header makes the compilation faster, but doesn't change anything else.

Why doesn't C++ support forward declaration of enums?

Georg
A: 

The answer to your question is to either go ahead and import the typedef header file or to use a generic type like NSInteger instead of the enum type.

However, there is more reason to not importing a header file than just compile speed.

Not importing a header file also reduces your inadvertent access to extraneous classes.

For example, say you have a TrackFileChanges class that tracks the file system for changes to a specific file, and you have a CachedFile class that stores cached data from a file. The latter might use a private ivar of type TrackFileChanges*, but for uses of CachedFile, this is simply an implementation detail (ideally, the ivar would be auto-generated with a private property using the new runtime, but thats not possible if you're using the old run time).

So clients that #import "CachedFile.h" probably do not need or want access to TrackFileChanges.h. And if they do, they should make it clear by #importing it themselves. By using @class TrackFileChanges instea of #import "TrackFileChanges.h" in CachedFile.h you improve the encapsulation.

But all that said, there is nothing awrong with importing a header file from a second header file if the second header wants to expose the first to all clients. For example, header files that declare classes need to be imported directly in subclassing header files, and header files declaring protocols might well be imported directly (although youy can use @protocol ABC; to avoid this).

Peter N Lewis