Objective-C: директива @class перед @interface?

В чем разница между этими двумя объявлениями класса? Я не понимаю, почему здесь используется @class. Благодарю.

@class TestClass;

@interface TestClass: UIView {
    UIImage *image1;
    UIImage *image2;
}

и

@interface TestClass: UIView {
    UIImage *image1;
    UIImage *image2;
}

Ответ 1

@class существует, чтобы разбить круговые зависимости. Скажем, у вас есть классы A и B.

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

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

Куриное; встретиться с яйцом. Это никогда не может быть скомпилировано, потому что интерфейс зависит от определения B и наоборот.

Таким образом, его можно исправить с помощью @class:

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

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

@class эффективно сообщает компилятору, что такой класс существует где-то, и, таким образом, указатели, объявленные указывать на экземпляры упомянутого класса, совершенно верны. Однако вы не можете вызвать метод в ссылке на экземпляр, тип которого определяется только как @class, потому что нет дополнительных метаданных, доступных компилятору (я не могу вспомнить, если он вернет сайт вызова для оценки как вызовите id или нет).

В вашем примере @class является безвредным, но совершенно ненужным.

Ответ 2

@class TestClass;

Это просто объявляет, что будет определен класс TestClass.

В этом случае (тот, который вы вставили) это не влияет ни на что, поэтому они одинаковы.

Однако, если вы собираетесь определить протокол, который будет использовать ваше имя класса (например, тип параметров, переданных делегату, например), вам необходимо объявить @class TestClass до определения протокола, так как ваш класс все еще не определено.

В общем случае, если вам нужно указать свое имя класса до того, как будет определено определение класса, вам сначала нужно выпустить объявление @class

Ответ 3

В соответствии с ответом Мэт нет абсолютно никакого смысла в объявлении @class в вашем коде. @class forward определяет класс, чтобы впоследствии компилятор знал, к какому обычному типу единицы вы обращаетесь. Поскольку Objective-C во время выполнения во многих случаях становится бесперспективным, то часто все, что должен знать компилятор, - достаточно, чтобы отличить вещь от атомного значения C.

Я собираюсь сделать удар в темноте и сказать, что, поскольку переменные экземпляра объявлены в @interface, вы смотрите на какой-то старый код. Поскольку это старый код, @class, вероятно, использовался где-то в другом месте (например, был объявлен протокол делегата) и только что оказался безвредным.

Ответ 4

@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

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

}