#import不能防止循环呼叫?

Oli*_*ver 2 import header objective-c include

我有两个类ClassA和Class B(它们是viewControllers).
A类是classB的委托.
ClassA"laucnhes"和ClassB的实例.
classA上的ClassB调用方法.

让我们说它是:

#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];
}
Run Code Online (Sandbox Code Playgroud)

这样做,A必须导入B,B必须导入A.

如果B不导入A(仅使用@class A),则来自A的used属性存在编译错误.
如果B导入A,则该ClassA* delegate行上存在编译错误.

为什么我有这些编译错误?#import不会再次保护递归调用吗?

我不需要解决方案来解决这个问题,我知道如何做到这一点.
但我想知道为什么我的#import会导致这些问题.这些不是#includes ......

zap*_*aph 6

在.h文件中更喜欢@class到#import.然后可以在.m实现文件中导入两者.

// 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];
}
Run Code Online (Sandbox Code Playgroud)

使用@class语句而不是#import也可以减少依赖性并使其余的更清晰.它还可以加快编译时间.


Pet*_*sey 5

为什么我有这些编译错误?#import不会再次保护递归调用吗?

#import防止重复将相同的标头导入同一模块,无论是否通过循环包含/导入.它通过不让你这样做来防止这种情况:只有#import头部的第一个工作; #import忽略相同标题的后续s.

在一个循环的#include情况下,预处理器会绕圈数次,然后在你编译之前就失败了.使用#import可以防止预处理器被楔入并让预处理器成功,但循环#import代码仍然是狡猾的,通常不会编译.

那么,根据您的具体情况而定.

对于您在问题中显示的代码,@class将在任一标题或两个标题中使用,实际上您应该在两者中使用它.您还需要#import两个.m文件中的两个标头.

如果B不导入A(仅使用@class A),则来自A的used属性存在编译错误.

如果你的意思是"在我使用类型属性的每个点都有编译错误ClassA *",那么是:你不能与那个对象交谈,因为你还没有导入它的接口,所以编译器不知道是什么消息你可以发送到一个ClassA实例.这就是您需要导入其界面的原因.

如果B导入A,则ClassA*delegateline上存在编译错误.

如果两个标题相互导入,那么你有:

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)
Run Code Online (Sandbox Code Playgroud)

如果没有一个接口在另一个接口之前没有其他接口在它之前,这是不可能的.这就是你正在进入的圈子 - #import存在要破坏的圈子.#include允许圆圈,从而被楔入:

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)
Run Code Online (Sandbox Code Playgroud)

因此#import.

因此,您无法从另一个导入每个标头.因此@class.

但是您仍然需要从每个模块导入每个标头.也就是说,实际上,您需要做的就是:@class在每个标头中使用并在每个模块中使用#import(在两个标头上).