我有两个类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];
}
这样做,A必须导入B,B必须导入A.
如果B不导入A(仅使用@class A),则来自A的已使用属性存在编译错误。
如果B导入A,则ClassA* delegate
行上存在编译错误。
为什么我有这些编译错误? #import不会再次保护递归调用吗?
我不需要解决方案来解决这个问题,我知道如何解决这个问题。
但我想知道为什么我的#import会导致这些问题。这些不是#includes ......
答案 0 :(得分: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];
}
使用@class语句而不是#import也可以减少依赖关系并使其余的更清晰。它还可以加快编译时间。
答案 1 :(得分:5)
为什么我有这些编译错误? #import不会再次保护递归调用吗?
#import
可以防止重复将相同的标头导入同一个模块,无论是否通过循环包含/导入。它通过不让你这样做来防止这种情况:只有标题的第一个#import
起作用;
#import
在循环#include
情况下,预处理器会绕圈数次,然后在编译之前使构建失败。使用#import
可以防止预处理器被楔入并让预处理器成功,但循环 - #import
代码仍然是狡猾的,通常不会编译。
所以,根据你的具体情况。
对于您在问题中显示的代码,@class
将在其中一个或两个标题中起作用,实际上您应该在两者中使用它。您还需要{。1}}两个.m文件中的两个标头。
如果B不导入A(仅使用@class A),则A中使用的属性存在编译错误。
如果你的意思是“在我使用#import
类型的属性的每个点都有编译错误”,那么是:你不能与那个对象交谈,因为你没有导入它的接口,所以编译器不知道您可以向ClassA *
实例发送哪些消息。这就是您需要导入其界面的原因。
如果B导入A,则ClassA *委托线上存在编译错误。
如果两个标题相互导入,那么你有:
ClassA
如果没有一个接口在另一个接口之前没有其他接口,那么这种方法是行不通的。这就是你遇到的圈子 - 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)
存在的圈子。 #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)
。
因此您无法从另一个导入每个标头。因此#import
。
但您仍需要从每个模块导入每个标头。也就是说,事实上,您需要做的就是:在每个标头中使用@class
,并在每个模块中使用@class
(在两个标头上)。
答案 2 :(得分:1)
通过声明
可以避免此编译投诉@class ClassB;
.h文件中的。然后可以将ClassB.h包含在.m文件中。
所以你是对的。与都市神话相反,#import的工作方式与#includes非常相似,因为编译器必须检查文件。
请参阅this(重复?)问题,了解您的哲学问题。
答案 3 :(得分:0)
我认为你会发现#import只有在成功包含一次后才能防止多次包含,可以这么说。
即,在您的情况下,它还没有成功导入classa.h,然后再要求它再次导入它,所以它会这样做。