我有以下代码:
#import <Foundation/Foundation.h>
#import "ServerRequest.h" // works even though this line is included
#import "ServerResponseRecord.h"
@protocol ServerRequestDelegate<NSObject>
-(void)request:(id)request gotResponseRecord:(ServerResponseRecord*)response;
-(void)request:(id)request gotError:(NSError*)error;
@end
它编译并运行良好。但是,如果我用以下方法替换方法声明:
-(void)request:(ServerRequest*)request gotResponseRecord:(ServerResponseRecord*)response;
-(void)request:(ServerRequest*)request gotError:(NSError*)error;
我在'ServerRequest'之前得到了意外的语法错误“error:expected')'。我认为这可能是一个问题的唯一原因是ServerRequestDelegate.h和ServerRequest.h #import彼此。但是,我不明白为什么代码适用于带有(id)请求的#import行。我也不明白为什么这是一个语法错误。
有人可以提供一个很好的解释吗?
答案 0 :(得分:26)
你已经暗示了这个解释:#import cycle。
我要做的第一件事是移除#include
并在@protocol
定义上方添加以下行:
@class ServerRequest;
这是一个前向类声明,可以帮助打破导入循环。查看this SO question了解更多详情。 Apple在this guide中也有一个简短的解释。
基本上,#import
'文件会导致编译器将该文件的整个文本带入相关文件中,尽管#import
比#include
更“智能”,但它并不意味着你免受导入错误的影响。 @class
声明是一种告诉编译器在不导入标头的情况下存在类的方法。当您只需要知道类名时使用它是合适的,但不关心它提供的方法。通常,您希望在.h文件中使用@class
,在.m文件中使用#import
,您实际上正在与该类进行交互。
答案 1 :(得分:0)
#import“循环”不是问题。 #import与#include相同,只是它跟踪文件并确保预处理器只在第一次读取它们。
通常当您收到类似错误时,由于包含文件中的问题。所以错误可能在ServerResponseRecord.h中,认为它可能是因为实际使用它声明的对象而被触发。如果没有看到完整的标题,就无法确切地说出发生了什么。