#import does not protect against circular calls?
I have two classes ClassA and Class B (they are viewControllers).
Class A is a delegate of classB. ClassA "laucnhes" and instance of ClassB. ClassB call methods on classA.Let's say it's :
#import "ClassB.h"
@interface ClassA : NSObject {
ClassB* subController;
}
- (void) doThis;
-------------------------------
#import "ClassA.h"
@interface ClassB : NSObject {
ClassA* delegate;
}
-------------------------------
@implementation ClassB
- (void) someMethod {
AnObject* myObj = [self.delegate.arr objectAtIndex:8];
[self.delegate doThis];
}
Doing that way, A must import B, and B must import A.
If B do not import A (with just @class A), there is a compile error for the used attribute from A.
If B imports A, there is a compile error on theClassA开发者_开发百科* delegate
line.
Why do I have those compile errors? Doesn't #import protect again recursive calls ?
I don't need a solution to solve that problem, I know how I may do this.
But I wonder why my #import cause those problems. These are not #includes...In .h files prefer @class to #import. Both can then be imported in the .m implementation files.
// ClassA.h -------------------------------
@class ClassB;
@interface ClassA : NSObject {
ClassB* subController;
}
- (void) doThis;
// ClassB.h -------------------------------
@class ClassA;
@interface ClassB : NSObject {
ClassA* delegate;
}
// ClassB.m -------------------------------
#import "ClassA.h"
#import "ClassB.h"
@implementation ClassB
- (void) someMethod {
AnObject* myObj = [self.delegate.arr objectAtIndex:8];
[self.delegate doThis];
}
Using @class statements instead of #import also reduces dependencies and makes the remaining ones more clear. It can also speed up compile times.
Why do I have those compile errors? Doesn't #import protect again recursive calls ?
#import
protects against repeatedly importing the same header into the same module, whether by circular includes/imports or not. It protects against that by not letting you do it: Only the first #import
of a header works; subsequent #import
s of the same header are ignored.
In a circular #include
situation, the preprocessor would go around the circle some number of times and then fail the build before you even get to compilation. Using #import
prevents the preprocessor from getting wedged and lets the preprocessor succeed, but circular-#import
code is still dodgy at best and usually will not compile.
So, on to your specific situation.
For the code you showed in your question, @class
will work in either or both headers, and indeed you should use it in both. You'll also need to #import
both headers in both .m files.
If B do not import A (with just @class A), there is a compile error for the used attribute from A.
If you mean “there is a compile error at each point where I use that attribute of type ClassA *
”, then yes: You can't talk to that object because you haven't imported its interface, so the compiler doesn't know what messages you can send to a ClassA
instance. That's why you need to import its interface.
If B imports A, there is a compile error on the ClassA* delegateline.
If both headers import each other, then you have this:
ClassA.m:
ClassA.h
ClassB.h
ClassA.h (ignored because this was already imported by ClassA.m)
ClassB.m:
ClassB.h
ClassA.h
ClassB.h (ignored because this was already imported by ClassB.m)
There is no way this can work without one interface preceding the other without the other interface preceding it. That's the circle you're running into—the circle that #import
exists to break. #include
allows the circle, and thereby gets wedged:
ClassA.m:
ClassA.h
ClassB.h
ClassA.h
ClassB.h
ClassA.h
ClassB.h
ClassA.h
ClassB.h
ClassA.h
ClassB.h
ClassA.h
ClassB.h
(fails at some point)
Hence #import
.
So you cannot import each header from the other. Hence @class
.
But you still need to import each header from each module. That is, in fact, exactly what you need to do: Use @class
in each header and use #import
(on both headers) in each module.
This compile complaint can be avoided by declaring
@class ClassB;
in the .h file. The ClassB.h can then be included into the .m file.
So you are right on that one. Contrary to urban myth, #imports work pretty much like #includes in the sense that the compiler has to check the file.
See this (duplicate?) question for your philosophical problem.
I think you'll find that #import only protects against multiple inclusion once it has already been successfully included once, so to speak.
ie, in your case, it hasn't successfully imported classa.h before it is asked to import it again, so it does so.
精彩评论