Objective C中的循环#import / @ class问题

时间:2009-11-13 19:06:43

标签: objective-c cocoa cocoa-touch import

我将用一个例子来恰当地说明我的困惑。我无法完全理解这一点。

在Cocoa touch中,我们有UIViewController及其子类UINavigationController。现在,UIVC有一个UINav类型的ivar,为了解决循环导入问题,他们使用@class UINavigationController。我假设他们#import "UINavigationController UIViewController.m(或某些人)。{/ p>

因此我的困惑是:UIViewController的子类如何知道UINavigationController中声明的方法?从UIViewController子类内部可以调用[self.navigationController popViewController],但该方法是如何知道的?

我唯一的想法是UINavigationController必须单独导入到每个子类(可能在前缀?)

有什么想法吗?

2 个答案:

答案 0 :(得分:1)

如果这个项目是使用其中一个Xcode模板创建的,那么UIKit中所有类的标题可能都包含在项目的预编译标题中。

答案 1 :(得分:0)

它不是隐藏的导入标题。子类“知道”超类“知道”的一切。这是单一继承设计的优势之一。考虑3个班级;

ClassA.h

#import <Foundation/Foundation.h>

@class ClassB;
@interface ClassA : NSObject {
    ClassB *bClass;
}
@property(nonatomic, retain)  ClassB *bClass;

@end

ClassA.m

#import "ClassA.h"
#import "ClassB.h"

@implementation ClassA
@synthesize bClass;

-(ClassB *) bClass{
    return [[ClassB alloc] init];
}
@end

ClassB的:

#import <Foundation/Foundation.h>

@class ClassA;
@interface ClassB : NSObject {
    ClassA *aClass;
    NSString *name;
}
@property(nonatomic, retain)  ClassA *aClass;
@property(nonatomic, retain)  NSString *name;

@end

ClassB.m

#import "ClassB.h"
#import "ClassA.h"

@implementation ClassB
@synthesize aClass;
@synthesize name;

-(NSString *) name { return @"steve";}
@end

现在创建一个ClassA的子类: ClassC.h

#import <Foundation/Foundation.h>
#import "ClassA.h"

@interface ClassC : ClassA {

}

@end

ClassC.m

#import "ClassC.h"
@implementation ClassC

@end

当您调用ClassC的bclass名称方法时:

#import "ClassC.h"
...
ClassC *c=[[ClassC alloc] init];
NSLog(@"c %@",[[c bClass] name]); //prints "c steve"

在超类实现文件中导入的标头固有的子类。

Edit01:

来自评论:

  

试试这个:在ClassA.h中定义一个宏,   然后尝试在ClassC.m中使用该宏   (没有导入ClassA.h)。它   不会编译

尽管如此,我认为这是不正确的。以下是编译和运行的实际代码:

ClassA.h

#import <Foundation/Foundation.h>

#define aMacro 5

@class ClassB;
@interface ClassA : NSObject {
    ClassB *bClass;
}
@property(nonatomic, retain)  ClassB *bClass;   
@end

ClassC.h

#import <Foundation/Foundation.h>
#import "ClassA.h"

@interface ClassC : ClassA {
}
-(void) logMacro;
@end

ClassC.m

#import "ClassC.h"

@implementation ClassC
-(void) logMacro{
    NSLog(@"aMacro=%d",aMacro);
}//-------------------------------------(void) logMacro------------------------------------
@end

运行时:

#import "ClassC.h" //the only header imported of the three classes ./////////
...
ClassC *c=[[ClassC alloc] init];
NSLog(@"c %@",[[c bClass] name]);
[c logMacro]; //prints 5

显然,ClassC.m只知道ClassA.h中定义的一个宏,它基于在ClassC.h中导入ClassA.h(它必须作为子类)。

ClassC不会知道ClassA.m中定义的宏,但这是因为实现中定义的宏实际上并不是该类的逻辑部分。 ClassA也不“了解”宏。这样的宏不在类的名称空间中,它只是编译器执行的简单文本替换。 ClassC不知道这样的替换,因为它知道ClassA在其中一种方法中使用了实际的'5'。 ClassC不能固有这样一个宏,因为没有固有的东西。

ClassC知道在ClassA中定义的宏,因为编译器生成的ClassC的真正逻辑头是由导入创建的链中所有头的并集。 ClassC 知道 ClassA知道的一切就像知道Foundation框架知道的一切。

ClassC以与ClassA相同的方式了解ClassB。 @class指令使编译器期待ClassB的定义,并在ClassA.m中找到它。在幕后没有秘密导入大量头文件。那是父母的问题。