web-dev-qa-db-ja.com

Objective-C:@interfaceの前に@classディレクティブ?

これら2つのクラス宣言の違いは何ですか?ここで@classが使用される理由がわかりません。ありがとう。

@class TestClass;

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

そして

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

@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は無害ですが、完全に不要です。

182
bbum
@class TestClass;

これは単に「クラスTestClassが定義される」と宣言するだけです。

この場合(貼り付けたもの)、これは何の効果もありません。したがって、これらは同じです。

ただし、クラス名を使用するプロトコルを定義する場合(たとえば、デリゲートに渡されるパラメーターのタイプとして)、クラスはプロトコル定義の前に@class TestClassを宣言する必要があります。まだ定義されていません。

一般に、クラス定義を作成する前にクラス名を指定する必要がある場合は、最初に@class宣言を発行する必要があります

18
poncha

マットの回答によると、@classコード内の宣言。 @class forwardはクラスを定義し、その結果、コンパイラが参照している一般的なユニットの種類を認識します。 Objective-Cは実行時にほとんど型のないため、多くの場合、コンパイラが実際に知る必要があるのはそれだけです-原子のC値と区別するのに十分です。

暗闇の中で突き刺して、インスタンス変数が@interfaceいくつかの古いコードを見ています。古いコードであるため、@classは、おそらくどこか別の場所にあり(たとえば、間に宣言された委任プロトコルがありました)、無害に取り残されたばかりです。

6
Tommy

@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

次に、クラスを使用している場合、クラスのインスタンスを作成するだけでなく、単一のインポートステートメントでプロトコルを実装することもできます。

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

}
3
vsanthanam510