子类化视图控制器:前向声明

Posted

技术标签:

【中文标题】子类化视图控制器:前向声明【英文标题】:Subclassing view controller: Forward declaration 【发布时间】:2014-10-07 15:54:52 【问题描述】:

我一直遵循拥有的规则:

类头文件中的@MyClassName

&&

#import "MyClassName" 在实现中

我现在决定子类化我的一个视图控制器。如果我覆盖了一个方法,那么我会收到以下消息:

类消息的接收者“MyClassName”是一个前向声明

为了解决这个问题,我需要将#import 放入头文件中,这似乎没有遵循我认为的最佳做法。

如果我误解了@class 的使用,有人可以解释一下吗?

或者,如果我做对了,有人可以解释一下你需要打破最佳实践并在子类化时在头文件中使用#import吗?

非常感谢。

编辑:

感谢您的回答。我想我需要添加更多细节来澄清我的情况并希望我的理解。这是我的基类的标题:

#import <UIKit/UIKit.h>
#import "CorePlot-CocoaTouch.h"

@class Organisation;

@interface LongCallDetailViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>

在我的实施中,我有

#import "Organisation.h"

我的子类标题包含以下内容:

#import "LongCallDetailViewController.h"

@interface LongCallSubclassViewController : LongCallDetailViewController

@end

如果我重写子类中的一个方法并尝试使用一个组织对象,它会给我上面所说的错误。因此,我要么需要将#import "Organisation.h" 添加到基类标题中,要么将#import "Organisation.h" 复制到子类实现文件中。在我看来,这两者都是错误的。

非常感谢。

【问题讨论】:

【参考方案1】:

在头文件中,您应该为您子类化的任何类导入其他头文件。您不需要为只是引用而不是子类化的类导入头文件。例如,头文件可能如下所示:

#import "MySuperClass.h"

@class MyObjectType;

@interface MySubClass : MySuperClass
@property (strong) MyObjectType *value;
@end

编辑: 根据您的新编辑,看起来您正在正确编写头文件。当您仅在范围内声明 @class 时,您将无法访问与该类关联的任何选择器或属性。可以在您不打算使用该类类型的选择器或属性的地方声明使用 @class 并仅传递引用(如我在上面描述的标题中),但只要您想做与对象有关的任何其他内容,您都需要导入描述@interface 的头文件。

在头文件中定义@class MyObjectType 时,通常期望#import "MyObjectType.h" 出现在关联的源文件中。头文件旨在作为结构声明,而源文件将包含实现。例如,与我上面描述的头文件关联的源文件可能如下所示:

#import "MySubClass.h"

#import "MyObjectType.h"

@implementation MySubClass
- (void)overriddenFunction 
  [self.value anObjectTypeSelector];

@end

当导入语句处于两个不同的范围时,您不应该考虑“复制”它们。当您在 LongCallDetailViewController 头文件中转发声明 @class Organisation 时,您的 LongCallDetailViewController 源文件中将有一个 #import "Organisation.h"。如果您还需要在LongCallSubclassViewController 类中访问此对象的属性和选择器,则需要在LongCallSubclassViewController 实现文件中访问#import "Organisation.h"。记住:实现文件不知道对方的内容;他们只知道头文件的内容。

【讨论】:

我已经编辑了我的问题,以更好地说明我面临的问题。谢谢。 非常感谢您更新您的答案。我希望有一种方法不必复制#import :-)。你的回答让我明白了。 如果您将#import "Organisation.h" 放在您的LongCallDetailViewController 标题中,您就不必输入该行两次。在这种情况下,我不知道我对“最佳实践”的立场是什么;它为潜在的子类提供了帮助,但也可能导致导入周期(如果您对导入真的很草率)。【参考方案2】:

#import 导入具有所有公共方法和属性的类的定义。

@import 预声明类,所以没有关于方法和属性的信息

您在以下情况下使用#import:

您是一个类的子类 - 导入您的类的其他类需要了解该类支持的所有方法。 您实现了一个协议 - 原因与上述相同。

【讨论】:

以上是关于子类化视图控制器:前向声明的主要内容,如果未能解决你的问题,请参考以下文章

iOS:使用 nib 子类化 UITableViewCell,进入 UIView(不是视图控制器)子类

使用插座子类化主视图控制器

子类化 UIView/UIViewController

Objective-C / iOS:为自定义视图子类化 UITableViewController

子类化 UISplitViewController 时出现奇怪的错误

将出口连接到子类视图控制器