6

I'm developing an iPhone app, and I'm kinda new to Objective-C and also the class.h and class.m structure.

Now, I have two classes that both need to have a variable of the other one's type. But it just seems impossible.

If in class1.m (or class2.m) I include class1.h, and then class2.h, I can't declare class2 variables in class1.h, if I include class2.h and then class1.h, I can't declare class1 variables in class2.h.

Hope you got my idea, because this is driving me nuts. Is it really impossible to accomplish this?

Thanks.

treznik
  • 7,955
  • 13
  • 47
  • 59
  • 4
    This might be what you are looking for: http://stackoverflow.com/questions/322597/objective-c-class-vs-import – teabot Jul 13 '09 at 13:56

2 Answers2

21

You can use the @class keyword to forward-declare a class in the header file. This lets you use the class name to define instance variables without having to #import the header file.

Class1.h

@class Class2;

@interface Class1
{
    Class2 * class2_instance;
}
...
@end

Class2.h

@class Class1;

@interface Class2
{
    Class1 * class1_instance;
}
...
@end

Note that you will still have to #import the appropriate header file in your .m files

Quinn Taylor
  • 44,553
  • 16
  • 113
  • 131
e.James
  • 116,942
  • 41
  • 177
  • 214
  • 1
    +1 In fact, some people strongly recommend ONLY doing it this way within your own code. Since you generally only need the class type name in the header (for variables, parameters, and return types) this tends to simplify your import chain, and makes all the header files faster to process. Definitely see the SO link @teabot provided just below the question as well. – Quinn Taylor Jul 13 '09 at 14:07
  • @Quinn Taylor: good point. I hardly ever use `#import` in my own header files, unless it is required for inheritance. – e.James Jul 13 '09 at 14:13
  • Thanks. But it doesn't seem to work all the way. I get this message when I use it. "warning: receiver "Class2" is a forward class and corresponding @interface may not exist". And when I try to access one of it's components, it errors out that that component does not exist. By appropriate header you mean it's own header? or both of them? – treznik Jul 13 '09 at 14:26
  • @skidding: Yes, each source file will have to include *both* headers in order to prevent that warning. – e.James Jul 13 '09 at 14:28
  • Hmm, nevermind, I just read the SO page from teabot's link and I think I've got it. – treznik Jul 13 '09 at 14:30
3

A circular dependency is often an indication of a design problem. Probably one or both of the classes have too many responsibilities. A refactoring that can emerge from a circular dependency is moving the interdependent functionality into its own class that the two original classes both consume.

Can you describe the functionality that each class requires from the other?

Aidan Ryan
  • 11,389
  • 13
  • 54
  • 86
  • Well. Basically Class1 creates an instance of Class2, which fires a script that loads an external image asynchronously, and when the images is loaded a method from Class2 is fired, which must fire a method from Class1. You may wonder then why do I need Class2 after all, where there are some added functionalities besides the image load so I need it. Hmm, I just realized, can I store the Class1 references as an type? – treznik Jul 13 '09 at 14:19
  • Sounds like a job for a delegate or event. Class2 does not need to know that Class1 in particular cares about the image load completion, just that there are others out there that want to know about it. Class2 should expose an event/notification that it fires when image load is complete. The consumers are responsible for subscribing and choosing what to do when the notification occurs. – Aidan Ryan Jul 13 '09 at 14:51
  • 2
    Here are many ways to implement loosely-coupled communication between objects: http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaFundamentals/CommunicatingWithObjects/CommunicateWithObjects.html – Aidan Ryan Jul 13 '09 at 14:53