开发者

#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 the ClassA开发者_开发百科* delegateline.

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 #imports 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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜