Objective c 目标C:@接口之前的@class指令?
这两个类声明之间有什么区别?我不明白这里为什么使用@class。谢谢Objective c 目标C:@接口之前的@class指令?,objective-c,syntax,Objective C,Syntax,这两个类声明之间有什么区别?我不明白这里为什么使用@class。谢谢 @class TestClass; @interface TestClass: UIView { UIImage *image1; UIImage *image2; } 及 这只是声明“将定义类TestClass” 在这种情况下(你粘贴的那个),这没有任何效果,所以它们是一样的 但是,如果要定义使用类名的协议(例如,作为传递给委托的参数类型),则需要在协议定义之前声明@class TestClass,因为尚
@class TestClass;
@interface TestClass: UIView {
UIImage *image1;
UIImage *image2;
}
及
这只是声明“将定义类TestClass”
在这种情况下(你粘贴的那个),这没有任何效果,所以它们是一样的
但是,如果要定义使用类名的协议(例如,作为传递给委托的参数类型),则需要在协议定义之前声明@class TestClass
,因为尚未定义类
一般来说,如果您需要在定义类之前提及您的类名,您需要首先发布
@class
声明,根据Matt的回答,代码中的@class
声明毫无意义@class
forward定义了一个类,以便编译器随后知道您所引用的单元的一般类型。由于Objective-C在运行时几乎是无类型的,这通常是编译器实际需要知道的全部内容——仅足以将其与原子C值区分开来
我想说的是,由于实例变量是在
@接口中声明的,所以您看到的是一些旧代码。因为它是旧代码,@class
可能以前在其他地方(例如,中间声明了一个委托协议),结果只是无害地搁浅了。@class
的存在打破了循环依赖关系。假设你有A班和B班
@interface A:NSObject
- (B*)calculateMyBNess;
@end
@interface B:NSObject
- (A*)calculateMyANess;
@end
鸡;遇到鸡蛋。这永远无法编译,因为A的接口依赖于B的定义,反之亦然
因此,可以通过使用@class
:
@class B;
@interface A:NSObject
- (B*)calculateMyBNess;
@end
@interface B:NSObject
- (A*)calculateMyANess;
@end
@class
有效地告诉编译器这样一个类存在于某个地方,因此,声明指向所述类实例的指针是完全有效的。但是,您无法对类型仅定义为@class
的实例引用调用方法,因为编译器没有可用的其他元数据(我不记得它是否将调用站点还原为通过id
进行的调用)
在您的示例中,@class
是无害的,但完全没有必要。@class在您需要为对象定义协议时非常方便,该对象通常会与您正在定义接口的对象交互。使用@class,您可以将协议定义保留在类的头中。这种委托模式通常用于Objective-C,并且通常比同时定义“MyClass.h”和“MyClassDelegate.h”更可取。这可能会导致一些令人困惑的导入问题
@class MyClass;
@protocol MyClassDelegate<NSObject>
- (void)myClassDidSomething:(MyClass *)myClass
- (void)myClass:(MyClass *)myClass didSomethingWithResponse:(NSObject *)reponse
- (BOOL)shouldMyClassDoSomething:(MyClass *)myClass;
- (BOOL)shouldMyClass:(MyClass *)myClass doSomethingWithInput:(NSObject *)input
@end
// MyClass hasn't been defined yet, but MyClassDelegate will still compile even tho
// params mention MyClass, because of the @class declaration.
// You're telling the compiler "it's coming. don't worry".
// You can't send MyClass any messages (you can't send messages in a protocol declaration anyway),
// but it's important to note that @class only lets you reference the yet-to-be-defined class. That's all.
// The compiler doesn't know anything about MyClass other than its definition is coming eventually.
@interface MyClass : NSObject
@property (nonatomic, assign) id<MyClassDelegate> delegate;
- (void)doSomething;
- (void)doSomethingWithInput:(NSObject *)input
@end
@class-MyClass;
@协议MyClassDelegate
-(void)MyClassDidThings:(MyClass*)MyClass
-(void)myClass:(myClass*)myClass做了一些有响应的事情:(NSObject*)响应
-(BOOL)应该MyClassDoSomething:(MyClass*)MyClass;
-(BOOL)应该MyClass:(MyClass*)MyClass doSomethingWithInput:(NSObject*)输入
@结束
//MyClass尚未定义,但MyClassDelegate仍将编译
//参数提到MyClass,因为@class声明。
//你告诉编译器“它来了,别担心”。
//您不能发送MyClass任何消息(无论如何也不能在协议声明中发送消息),
//但需要注意的是,@class只允许引用尚未定义的类。这就是全部。
//编译器对MyClass一无所知,只知道它的定义即将到来。
@接口MyClass:NSObject
@属性(非原子,赋值)id委托;
-(无效)剂量测定;
-(void)doSomethingWithInput:(NSObject*)输入
@结束
然后,当您使用该类时,您既可以创建该类的实例,也可以使用单个import语句实现该协议
#import "MyClass.h"
@interface MyOtherClass()<MyClassDelegate>
@property (nonatomic, strong) MyClass *myClass;
@end
@implementation MyOtherClass
#pragma mark - MyClassDelegate Protocol Methods
- (void)myClassDidSomething:(MyClass *)myClass {
NSLog(@"My Class Did Something!")
}
- (void)myClassDidSomethingWithResponse:(NSObject *)response {
NSLog(@"My Class Did Something With %@", response);
}
- (BOOL)shouldMyClassDoSomething {
return YES;
- (BOOL)shouldMyClassDoSomethingWithInput:(NSObject *)input {
if ([input isEqual:@YES]) {
return YES;
}
return NO;
}
- (void)doSomething {
self.myClass = [[MyClass alloc] init];
self.myClass.delegate = self;
[self.myClass doSomething];
[self.myClass doSomethingWithInput:@0];
}
#导入“MyClass.h”
@接口类()
@属性(非原子,强)MyClass*MyClass;
@结束
@MyOtherClass的实现
#pragma标记-MyClassDelegate协议方法
-(void)MyClassDidThings:(MyClass*)MyClass{
NSLog(@“我的班级做了些什么!”)
}
-(void)myClassDidSomethingWithResponse:(NSObject*)响应{
NSLog(@“我的班级用%@”做了一些事情”,回复);
}
-(BOOL)我的班级应该做些什么{
返回YES;
-(BOOL)应该MyClassDoSomethingWithinput:(NSObject*)输入{
如果([输入相等:@YES]){
返回YES;
}
返回否;
}
-(无效)剂量{
self.myClass=[[myClass alloc]init];
self.myClass.delegate=self;
[self.myClass doSomething];
[self.myClass doSomethingWithInput:@0];
}
我希望我能给另一个+1,只是为了“鸡,遇到蛋”顺便说一句,它会恢复到id
评估。有没有特别的原因,为什么有些人把@class
放在他们的.h文件中,然后在他们的.m文件中导入必要的头文件,而其他人可能只在当前的class头文件中导入.h文件?只是好奇,谢谢@bbum@JoshValdivieso您仍然会很快得到循环依赖,一般的模式是最小化头文件中导入的数量,因为它用于显著减少编译时间(在今天和预编译头的时代,情况并非如此).我在协议之前见过最多的实现。谢谢分享!
@class MyClass;
@protocol MyClassDelegate<NSObject>
- (void)myClassDidSomething:(MyClass *)myClass
- (void)myClass:(MyClass *)myClass didSomethingWithResponse:(NSObject *)reponse
- (BOOL)shouldMyClassDoSomething:(MyClass *)myClass;
- (BOOL)shouldMyClass:(MyClass *)myClass doSomethingWithInput:(NSObject *)input
@end
// MyClass hasn't been defined yet, but MyClassDelegate will still compile even tho
// params mention MyClass, because of the @class declaration.
// You're telling the compiler "it's coming. don't worry".
// You can't send MyClass any messages (you can't send messages in a protocol declaration anyway),
// but it's important to note that @class only lets you reference the yet-to-be-defined class. That's all.
// The compiler doesn't know anything about MyClass other than its definition is coming eventually.
@interface MyClass : NSObject
@property (nonatomic, assign) id<MyClassDelegate> delegate;
- (void)doSomething;
- (void)doSomethingWithInput:(NSObject *)input
@end
#import "MyClass.h"
@interface MyOtherClass()<MyClassDelegate>
@property (nonatomic, strong) MyClass *myClass;
@end
@implementation MyOtherClass
#pragma mark - MyClassDelegate Protocol Methods
- (void)myClassDidSomething:(MyClass *)myClass {
NSLog(@"My Class Did Something!")
}
- (void)myClassDidSomethingWithResponse:(NSObject *)response {
NSLog(@"My Class Did Something With %@", response);
}
- (BOOL)shouldMyClassDoSomething {
return YES;
- (BOOL)shouldMyClassDoSomethingWithInput:(NSObject *)input {
if ([input isEqual:@YES]) {
return YES;
}
return NO;
}
- (void)doSomething {
self.myClass = [[MyClass alloc] init];
self.myClass.delegate = self;
[self.myClass doSomething];
[self.myClass doSomethingWithInput:@0];
}