Objective-C:@interface之前的@class指令?

Rya*_*yan 75 syntax objective-c

这两个类声明有什么区别?我不明白为什么在这里使用@class.谢谢.

@class TestClass;

@interface TestClass: UIView {
    UIImage *image1;
    UIImage *image2;
}
Run Code Online (Sandbox Code Playgroud)

@interface TestClass: UIView {
    UIImage *image1;
    UIImage *image2;
}
Run Code Online (Sandbox Code Playgroud)

bbu*_*bum 187

@class存在以打破循环依赖.假设你有A班和B班.

@interface A:NSObject
- (B*)calculateMyBNess;
@end

@interface B:NSObject
- (A*)calculateMyANess;
@end
Run Code Online (Sandbox Code Playgroud)

鸡; 遇见鸡蛋.这永远无法编译,因为A的接口依赖于B的定义,反之亦然.

因此,它可以通过使用@class:

@class B;
@interface A:NSObject
- (B*)calculateMyBNess;
@end

@interface B:NSObject
- (A*)calculateMyANess;
@end
Run Code Online (Sandbox Code Playgroud)

@class有效地告诉编译器这样的类存在于某处,因此,声明指向所述类的实例的指针是完全有效的.但是,您无法在实例引用上调用方法,该实例引用的类型仅定义为a,@class因为编译器没有可用的其他元数据(我不记得它是否将调用站点恢复为通过id或者通过调用进行评估)不).

在你的例子中,它@class是无害的,但完全没有必要.

  • 我希望我能为"鸡,遇见鸡蛋"另外+1 (22认同)
  • 顺便说一句,它确实回归到`id`评估. (4认同)
  • @JoshValdivieso您仍然会很快得到循环依赖关系,并且通用模式是最小化头文件中的导入数,因为它用于显着减少编译时间(在当天和时代的情况下并非如此)预编译头文件). (4认同)

pon*_*cha 18

@class TestClass;
Run Code Online (Sandbox Code Playgroud)

这仅仅声明"将定义类TestClass".

在这种情况下(你粘贴的那个)这没有任何影响,所以这些是相同的.

但是,如果您要定义一个使用您的类名的协议(例如,作为传递给委托的参数类型),您将需要@class TestClass在协议定义之前声明,因为您的类仍未定义.

通常,如果在创建类定义之前需要提及类名,则需要先发出@class声明


Tom*_*mmy 7

根据Matt的回答@class,你的代码中的声明绝对没有意义.@classforward定义了一个类,以便编译器随后知道您所引用的一般类型的单元.由于Objective-C在运行时几乎没有类型,这通常是编译器实际需要知道的全部 - 足以将事物与原子C值区分开来.

我将在黑暗中采取刺,并说,因为实例变量是在@interface你正在查看一些旧代码时声明的.因为它是旧的代码,@class可能曾经在其他地方(例如,在其间声明了委托协议)并且刚刚结束了无害的搁浅.


vsa*_*510 5

当您需要为一个对象定义一个协议时,@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
Run Code Online (Sandbox Code Playgroud)

然后,当您使用该类时,您既可以创建该类的实例,也可以使用单个导入语句实现协议

#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];

}
Run Code Online (Sandbox Code Playgroud)