2012-07-18 12 views
51

ObjectProperties.hのObjective-Cプロトコルフォワード宣言

@protocol ObjectProperties <NSObject> 

@property (strong, nonatomic) NSString *name; 
@property (strong, nonatomic) NSDate *date; 
@property (assign, nonatomic) int64_t index; 

@end 

ClassA.h

#import <Foundation/Foundation.h> 

@protocol ObjectProperties; 

@interface ClassA : NSObject <ObjectProperties> 

- (void)specialSauce; 

@end; 

ManagedClassA.h

#import <CoreData/CoreData.h> 

@protocol ObjectProperties; 

@interface ManagedClassA : NSManagedObject <ObjectProperties> 

- (void)doSomething; 

@end; 

上記のコード例では、.hファイルのプロトコルをCore Dataオブジェクトとプレーンオールバニラオブジェクトの両方で使用するように定義しました。準拠しているクラスを持つことは "ノイズ"のように思える#プロトコルをそのヘッダにインポートする。上に示したように、実装ファイルにプロトコル&のインポートを宣言しておくと、より洗練されたものになります。しかし、このようにそれをやったときに、Xcodeは警告をスロー:

Cannot find protocol definition for 'ObjectProperties'

コードをコンパイルし、主に動作します。私は主に、Core Dataがスカラープロパティのgetters/setterを動的に作成しようとしているために、いくつかのファンクがあると言いますが、それはおそらく私が端に当たったためです。

もちろん、最も顕著な回避策は、プロトコルヘッダーをクラスヘッダーにインポートすることです。

私の理解が正しい場合(私の知識は非常に最近取得されているので、私が間違っている可能性があります)、プロトコルを自分のクラスヘッダーにインポートしてプロトコルを変更すると、私のクラスをインポートするファイルは再コンパイルする必要があります。

このタイプの問題を解決する正しい方法は何ですか?

+0

私にも同様の問題がありますが、Swiftプロトコルがあります。 – Alper

答えて

93

あなたが前方スーパークラスまたは、それはに準拠したプロトコルを宣言することはできません。そのような場合は、ヘッダーを含める必要があります。これは、(スーパークラスの場合)スーパークラスのインスタンス変数とメソッドがクラスの一部になるためです。 (プロトコルの場合)プロトコルのメソッドは、明示的に宣言する必要なく、クラスで宣言されたメソッドになります。 (つまり、あなたのクラスのヘッダを含む他の人は、自分で宣言したかのようにクラスがそれらのメソッドを宣言していることを知ります)可能性があるこの唯一の方法は、 。

#import <SomeClass.h> 
#import <SomeProtocol.h> // these two must be imported 

@interface MyClass : SomeClass <SomeProtocol> 
@end 

前方宣言は、変数の型(具体的には、オブジェクトポインタ変数)に現れるものに役立ちます。オブジェクトポインタはすべて同じサイズであり、実行時にオブジェクトポインタの種類によって違いはありません(オブジェクトポインタの型の概念はコンパイル時のものです)。したがって、これらのタイプのクラスに含まれるものを正確に知る必要は本当にありません。こうして彼らは前方に宣言することができます。

@class SomeClass; 
@protocol SomeProtocol; // you can forward-declare these 

@interface MyClass { 
    SomeClass *var1; 
    id<SomeProtocol> var2; 
} 
@end 
4

はい、すべてのファイルを再コンパイルする必要がありますが、これは必要です。クラスヘッダーをインポートするファイルは、実装するプロトコルに関連するメソッドを知る必要があります。その定義を.mファイルに入れないと、1つのファイルだけが表示されます(.mファイルは決してインポートされないため)。前方宣言クラスと同じではありません。プロトコルを宣言する場合は、前方宣言と同じスコープ内に表示されるどこかに宣言する必要があります。これが同じファイル内にない例は考えられません。 ARCでは

これはARCが宣言されたメソッドのメモリ管理について知っておく必要があるため、エラーになります(彼らは1つのインスタンス、内部ポインタなどを返すのですか?)

2

MyClass.hであなたのクラスを宣言することにより、スーパークラスのすべてのヘッダーファイルと、MyClass.hファイルで採用したプロトコルをインポートする必要があります。 Objective-cのプロトコルは、継承のバリアント型とみなされます。

通常、前方宣言はクラスのメンバー宣言で使用されます。

1

プロトコルに準拠していることを宣言しているので、プロトコルを含むヘッダーを#importする必要があります。

これは、スーパークラスを#importing、というよりも前方にそれを宣言することと同じです。

@class Foo; 

@interface Bar : Foo 
// Will get error: attempting to use the forward class 'Foo' as superclass of 'Bar' 
@end;